summaryrefslogtreecommitdiff
path: root/Midi.h
diff options
context:
space:
mode:
Diffstat (limited to 'Midi.h')
-rw-r--r--Midi.h191
1 files changed, 191 insertions, 0 deletions
diff --git a/Midi.h b/Midi.h
new file mode 100644
index 0000000..5459e7e
--- /dev/null
+++ b/Midi.h
@@ -0,0 +1,191 @@
+/*
+ * Midi.h: Header for MIDI processing library, Arduino version
+ *
+ * (c) 2003-2008 Tymm Twillman <tymm@booyaka.com>
+ *
+ * This file is part of Tymm's Arduino Midi Library.
+ *
+ * Tymm's Arduino Midi Library is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * Tymm's Arduino Midi Library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Tymm's Arduino Midi Library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MIDI_H
+#define MIDI_H
+
+#include "HardwareSerial.h"
+
+
+/*
+ * This is the Midi class. If you are just sending Midi data, you only need to make an
+ * instance of the class, passing it your serial port -- in most cases it looks like
+ *
+ * Midi midi(Serial);
+ *
+ * then you don't need to do anything else; you can start using it to send Midi messages,
+ * e.g.
+ *
+ * midi.sendNoteOn(1, note, velocity);
+ *
+ * If you are using it to receive Midi data, it's a little more complex & you will need
+ * to subclass the Midi class.
+ *
+ * For people not used to C++ this may look confusing, but it's actually pretty easy.
+ * Note that you only need to write the functions for event types you want to handle.
+ * They should match the names & prototypes of the functions in the class; look at
+ * the functions in the Midi class below that have the keyword "virtual" to see which
+ * ones you can use.
+ *
+ * Here's an example of one that takes NOTE ON, NOTE OFF, and CONTROL CHANGE:
+ *
+ * class MyMidi : public Midi {
+ * public:
+ *
+ * // Need this to compile; it just hands things off to the Midi class.
+ * MyMidi(HardwareSerial &s) : Midi(s) {}
+ *
+ * void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity)
+ * {
+ * if (note == 40) {digitalWrite(13, HIGH); }
+ * }
+ *
+ * void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity)
+ * {
+ * if (note == 40) { digitalWrite(13, LOW); }
+ * }
+ *
+ * void handleControlChange(unsigned int channel, unsigned int controller,
+ * unsigned int value)
+ * {
+ * analogWrite(6, value * 2);
+ * }
+ *
+ * Then you need to make an instance of this class:
+ *
+ * MyMidi midi(Serial);
+ *
+ * If receiving Midi data, you also need to call the poll function every time through
+ * loop(); e.g.
+ *
+ * void loop() {
+ * midi.poll();
+ * }
+ *
+ * This causes the Midi class to read data from the serial port and process it.
+ */
+
+class Midi {
+private:
+ // The serial port used by this Midi instance (it takes complete control over the port)
+ HardwareSerial serial_;
+
+ /* Private Receive Parameters */
+
+ // The channel this Midi instance receives data for (0 means all channels)
+ int channelIn_;
+
+ // These are for keeping track of partial Midi messages as bytes come in
+ int recvMode_;
+ int recvByteCount_;
+ int recvEvent_;
+ int recvArg0_;
+ int recvBytesNeeded_;
+ int lastStatusSent_;
+
+ /* Private Send Parameters */
+
+ // This controls whether every Midi message gets a command byte sent with it
+ // (Midi can just send a single command byte and then stream events without
+ // sending the command each time)
+ bool sendFullCommands_;
+
+ /* Internal functions */
+
+ // Called whenever data is read from the serial port
+ void recvByte(int byte);
+
+ // This doesn't work -- by making it private, we ensure nobody ever calls it
+ Midi();
+
+public:
+ // Set this parameter to anything other than 0 to cause every MIDI update to
+ // include a copy of the current event (e.g. for every note off to include
+ // the NOTE OFF event) -- by default, if an event is the same type of event as
+ // the last one sent, the event byte isn't sent; just the new note/velocity
+ static const unsigned int PARAM_SEND_FULL_COMMANDS = 0x1000;
+
+ // Use this parameter to update the channel the MIDI code is looking for messages
+ // to. 0 means "all channels".
+ static const unsigned int PARAM_CHANNEL_IN = 0x1001;
+
+
+ // Constructor -- generally just use e.g. "Midi midi(Serial);"
+ Midi(HardwareSerial &serial);
+
+ // Call to start the serial port, at given baud. For many applications
+ // the default parameters are just fine (which will cause messages for all
+ // MIDI channels to be delivered)
+ void begin(unsigned int channel = 0, unsigned long baud = 31250);
+
+
+ // Changes the updateable parameters (params are Midi::PARAM_SEND_FULL_COMMANDS or
+ // Midi::PARAM_CHANNEL_IN -- see above for what they mean)
+ void setParam(unsigned int param, unsigned int val);
+
+ // Get current values for the user updateable parameters (params, etc same as above)
+ unsigned int getParam(unsigned int param);
+
+
+ // poll() should be called every time through loop() IF dealing with incoming MIDI
+ // (if you're only SENDING MIDI events from the Arduino, you don't need to call
+ // poll); it causes data to be read from the serial port and processed.
+ void poll();
+
+ // Call these to send MIDI messages of the given types
+ void sendNoteOff(unsigned int channel, unsigned int note, unsigned int velocity);
+ void sendNoteOn(unsigned int channel, unsigned int note, unsigned int velocity);
+ void sendVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity);
+ void sendControlChange(unsigned int channel, unsigned int controller, unsigned int value);
+ void sendProgramChange(unsigned int channel, unsigned int program);
+ void sendAfterTouch(unsigned int channel, unsigned int velocity);
+ void sendPitchChange(unsigned int pitch);
+ void sendSongPosition(unsigned int position);
+ void sendSongSelect(unsigned int song);
+ void sendTuneRequest(void);
+ void sendSync(void);
+ void sendStart(void);
+ void sendContinue(void);
+ void sendStop(void);
+ void sendActiveSense(void);
+ void sendReset(void);
+
+ // Overload these in a subclass to get MIDI messages when they come in
+ virtual void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity);
+ virtual void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity);
+ virtual void handleVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity);
+ virtual void handleControlChange(unsigned int channel, unsigned int controller, unsigned int value);
+ virtual void handleProgramChange(unsigned int channel, unsigned int program);
+ virtual void handleAfterTouch(unsigned int channel, unsigned int velocity);
+ virtual void handlePitchChange(unsigned int pitch);
+ virtual void handleSongPosition(unsigned int position);
+ virtual void handleSongSelect(unsigned int song);
+ virtual void handleTuneRequest(void);
+ virtual void handleSync(void);
+ virtual void handleStart(void);
+ virtual void handleContinue(void);
+ virtual void handleStop(void);
+ virtual void handleActiveSense(void);
+ virtual void handleReset(void);
+};
+
+#endif /* #ifndef MIDI_H ... */