From e84af245064722137962d10e2ad663677ff226aa Mon Sep 17 00:00:00 2001 From: Cameron White Date: Sun, 21 Jun 2015 13:36:48 -0400 Subject: [PATCH] Initial work on a MIDI exporter. --- source/CMakeLists.txt | 2 ++ source/midi/CMakeLists.txt | 13 ++++++++ source/midi/midievent.cpp | 37 +++++++++++++++++++++ source/midi/midievent.h | 60 +++++++++++++++++++++++++++++++++++ source/midi/midieventlist.cpp | 18 +++++++++++ source/midi/midieventlist.h | 44 +++++++++++++++++++++++++ source/midi/midifile.cpp | 30 ++++++++++++++++++ source/midi/midifile.h | 39 +++++++++++++++++++++++ 8 files changed, 243 insertions(+) create mode 100644 source/midi/CMakeLists.txt create mode 100644 source/midi/midievent.cpp create mode 100644 source/midi/midievent.h create mode 100644 source/midi/midieventlist.cpp create mode 100644 source/midi/midieventlist.h create mode 100644 source/midi/midifile.cpp create mode 100644 source/midi/midifile.h diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 20a283127..8e214e891 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -8,6 +8,7 @@ add_subdirectory(app) add_subdirectory(audio) add_subdirectory(dialogs) add_subdirectory(formats) +add_subdirectory(midi) add_subdirectory(painters) add_subdirectory(score) add_subdirectory(widgets) @@ -31,6 +32,7 @@ target_link_libraries(powertabeditor ptedialogs ptewidgets pteaudio + ptemidi rtmidi ptepainters pteformats diff --git a/source/midi/CMakeLists.txt b/source/midi/CMakeLists.txt new file mode 100644 index 000000000..32823baed --- /dev/null +++ b/source/midi/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 2.8.9) + +add_library(ptemidi + midievent.cpp + midieventlist.cpp + midifile.cpp + + midievent.h + midieventlist.h + midifile.h +) + +cotire(ptemidi) diff --git a/source/midi/midievent.cpp b/source/midi/midievent.cpp new file mode 100644 index 000000000..8ca025259 --- /dev/null +++ b/source/midi/midievent.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015 Cameron White + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +#include "midievent.h" + +MidiEvent::MidiEvent(int tick, StatusByte status, std::vector data, + int system, int position, int player, int instrument) + : myTick(tick), + myStatusByte(status), + myData(std::move(data)), + mySystem(system), + myPosition(position), + myPlayer(player), + myInstrument(instrument) +{ +} + +MidiEvent MidiEvent::endOfTrack(int tick) +{ + return MidiEvent(tick, StatusByte::MetaMessage, + { static_cast(MetaType::TrackEnd), 0 }, -1, -1, + -1, -1); +} diff --git a/source/midi/midievent.h b/source/midi/midievent.h new file mode 100644 index 000000000..7c8ba5b65 --- /dev/null +++ b/source/midi/midievent.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 Cameron White + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +#ifndef MIDI_MIDIEVENT_H +#define MIDI_MIDIEVENT_H + +#include +#include + +enum class StatusByte : uint8_t +{ + MetaMessage = 0xff +}; + +enum class MetaType : uint8_t +{ + TrackEnd = 0x2f +}; + +class MidiEvent +{ +public: + MidiEvent(const MidiEvent &) = default; + MidiEvent(MidiEvent &&) = default; + + int getTicks() const { return myTick; } + StatusByte getStatusByte() const { return myStatusByte; } + const std::vector &getData() const { return myData; } + + static MidiEvent endOfTrack(int tick); + +private: + MidiEvent(int tick, StatusByte status, std::vector data, + int system, int position, int player, int instrument); + + int myTick; // TODO - does this need to be 64-bit for absolute times? + StatusByte myStatusByte; + std::vector myData; + + int mySystem; + int myPosition; + int myPlayer; + int myInstrument; +}; + +#endif diff --git a/source/midi/midieventlist.cpp b/source/midi/midieventlist.cpp new file mode 100644 index 000000000..3e02b9bea --- /dev/null +++ b/source/midi/midieventlist.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2015 Cameron White + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +#include "midieventlist.h" diff --git a/source/midi/midieventlist.h b/source/midi/midieventlist.h new file mode 100644 index 000000000..461b9dbf4 --- /dev/null +++ b/source/midi/midieventlist.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 Cameron White + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +#ifndef MIDI_MIDIEVENTLIST_H +#define MIDI_MIDIEVENTLIST_H + +#include +#include + +class MidiEventList +{ +public: + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + + void append(MidiEvent &&event) + { + myEvents.push_back(std::forward(event)); + } + + iterator begin() { return myEvents.begin(); } + iterator end() { return myEvents.end(); } + const_iterator begin() const { return myEvents.begin(); } + const_iterator end() const { return myEvents.end(); } + +private: + std::vector myEvents; +}; + +#endif diff --git a/source/midi/midifile.cpp b/source/midi/midifile.cpp new file mode 100644 index 000000000..07a498e03 --- /dev/null +++ b/source/midi/midifile.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015 Cameron White + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +#include "midifile.h" + +static const int theDefaultPPQ = 480; + +MidiFile::MidiFile(const Score & score) + : myTicksPerBeat(theDefaultPPQ) +{ + // For now, just add some empty event lists. + MidiEventList temp; + temp.append(MidiEvent::endOfTrack(0)); + myTracks.push_back(temp); + myTracks.push_back(temp); +} diff --git a/source/midi/midifile.h b/source/midi/midifile.h new file mode 100644 index 000000000..08fc73e34 --- /dev/null +++ b/source/midi/midifile.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 Cameron White + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +#ifndef MIDI_MIDIFILE_H +#define MIDI_MIDIFILE_H + +#include +#include + +class Score; + +class MidiFile +{ +public: + MidiFile(const Score &score); + + int getTicksPerBeat() const { return myTicksPerBeat; } + const std::vector &getTracks() const { return myTracks; } + +private: + int myTicksPerBeat; + std::vector myTracks; +}; + +#endif