Merge branch 'release/4.2'
This commit is contained in:
commit
67f6b001ab
14
README.md
14
README.md
|
|
@ -1,9 +1,9 @@
|
||||||
#Arduino MIDI Library v4.1
|
#Arduino MIDI Library v4.2
|
||||||
|
|
||||||
This library enables MIDI I/O communications on the Arduino serial ports.
|
This library enables MIDI I/O communications on the Arduino serial ports.
|
||||||
The purpose of this library is not to make a big synthetizer out of an Arduino board, the application remains yours. However, it will help you interfacing it with other MIDI devices.
|
The purpose of this library is not to make a big synthetizer out of an Arduino board, the application remains yours. However, it will help you interfacing it with other MIDI devices.
|
||||||
|
|
||||||
Download the latest version [here](https://github.com/FortySevenEffects/arduino_midi_library/releases/download/4.1/Arduino_MIDI_Library_v4.1.zip).
|
Download the latest version [here](https://github.com/FortySevenEffects/arduino_midi_library/releases/latest).
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
* Compatible with all Arduino boards (and clones with an AVR processor)
|
* Compatible with all Arduino boards (and clones with an AVR processor)
|
||||||
|
|
@ -18,6 +18,7 @@ Download the latest version [here](https://github.com/FortySevenEffects/arduino_
|
||||||
|
|
||||||
|
|
||||||
#### Changelog
|
#### Changelog
|
||||||
|
* 11/06/2014 : Version 4.2 released. Bug fix for SysEx, overridable template settings.
|
||||||
* 16/04/2014 : Version 4.1 released. Bug fixes regarding running status.
|
* 16/04/2014 : Version 4.1 released. Bug fixes regarding running status.
|
||||||
* 13/02/2014 : Version 4.0 released. Moved to GitHub, added multiple instances & software serial support, and a few bug fixes.
|
* 13/02/2014 : Version 4.0 released. Moved to GitHub, added multiple instances & software serial support, and a few bug fixes.
|
||||||
* 29/01/2012 : Version 3.2 released. Release notes are [here](http://sourceforge.net/news/?group_id=265194)
|
* 29/01/2012 : Version 3.2 released. Release notes are [here](http://sourceforge.net/news/?group_id=265194)
|
||||||
|
|
@ -26,7 +27,7 @@ Download the latest version [here](https://github.com/FortySevenEffects/arduino_
|
||||||
* 14/12/2009 : Version 2.5 released.
|
* 14/12/2009 : Version 2.5 released.
|
||||||
* 28/07/2009 : Version 2.0 released.
|
* 28/07/2009 : Version 2.0 released.
|
||||||
* 28/03/2009 : Simplified version of MIDI.begin, Fast mode is now on by default.
|
* 28/03/2009 : Simplified version of MIDI.begin, Fast mode is now on by default.
|
||||||
* 08/03/2009 : Thru method operationnal. Added some features to enable thru.
|
* 08/03/2009 : Thru method operational. Added some features to enable thru.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -35,9 +36,10 @@ Download the latest version [here](https://github.com/FortySevenEffects/arduino_
|
||||||
|
|
||||||
### What do I need to do?
|
### What do I need to do?
|
||||||
|
|
||||||
* Download the library ([link](https://github.com/FortySevenEffects/arduino_midi_library/releases/download/4.1/Arduino_MIDI_Library_v4.1.zip))
|
* Download the library ([link](https://github.com/FortySevenEffects/arduino_midi_library/releases/latest))
|
||||||
* Follow the installation instructions there: http://arduino.cc/en/Guide/Libraries
|
* Follow the installation instructions there: http://arduino.cc/en/Guide/Libraries
|
||||||
* Include the library in your sketch using the menu in the IDE, or type `#include <MIDI.h>`
|
* Include the library in your sketch using the menu in the IDE, or type `#include <MIDI.h>`
|
||||||
|
* Create the MIDI instance using `MIDI_CREATE_DEFAULT_INSTANCE();` or take a look at the documentation for custom serial port, settings etc..
|
||||||
|
|
||||||
You are now ready to use the library. Look at the reference page to learn how to use it, or the examples given. Just don't forget to enable the I/O communications with MIDI.begin...
|
You are now ready to use the library. Look at the reference page to learn how to use it, or the examples given. Just don't forget to enable the I/O communications with MIDI.begin...
|
||||||
|
|
||||||
|
|
@ -46,9 +48,6 @@ You are now ready to use the library. Look at the reference page to learn how to
|
||||||
|
|
||||||
See the extended reference [here](http://arduinomidilib.fortyseveneffects.com) ([Mirror](http://fortyseveneffects.github.io/arduino_midi_library/)).
|
See the extended reference [here](http://arduinomidilib.fortyseveneffects.com) ([Mirror](http://fortyseveneffects.github.io/arduino_midi_library/)).
|
||||||
|
|
||||||
To know how to use the callback feature, see the dedicated page [here](http://playground.arduino.cc/Main/MIDILibraryCallbacks).
|
|
||||||
|
|
||||||
|
|
||||||
### Using MIDI.begin
|
### Using MIDI.begin
|
||||||
|
|
||||||
In the `setup()` function of the Arduino, you must call the `MIDI.begin()` method. If you don't give any argument to this method, the input channel for MIDI in will be set to 1 (channels are going from 1 to 16, plus `MIDI_CHANNEL_OMNI to listen to all channels at the same time).
|
In the `setup()` function of the Arduino, you must call the `MIDI.begin()` method. If you don't give any argument to this method, the input channel for MIDI in will be set to 1 (channels are going from 1 to 16, plus `MIDI_CHANNEL_OMNI to listen to all channels at the same time).
|
||||||
|
|
@ -78,4 +77,3 @@ Take a look at [the MIDI.org schematic](http://www.midi.org/techspecs/electrispe
|
||||||
if you have any comment or support request to make, feel free to contact me: francois.best@fortyseveneffects.com
|
if you have any comment or support request to make, feel free to contact me: francois.best@fortyseveneffects.com
|
||||||
|
|
||||||
You can also get informations about bug fixes and updates on my twitter account: [@fortysevenfx](http://twitter.com/fortysevenfx).
|
You can also get informations about bug fixes and updates on my twitter account: [@fortysevenfx](http://twitter.com/fortysevenfx).
|
||||||
|
|
||||||
|
|
|
||||||
2370
doc/Doxyfile
2370
doc/Doxyfile
File diff suppressed because it is too large
Load Diff
|
|
@ -37,6 +37,7 @@
|
||||||
\example MIDI_Bench.ino
|
\example MIDI_Bench.ino
|
||||||
\example MIDI_DualMerger.ino
|
\example MIDI_DualMerger.ino
|
||||||
\example MIDI_Input.ino
|
\example MIDI_Input.ino
|
||||||
|
\example MIDI_SimpleSynth.ino
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
// Here, when receiving any message on channel 4, the Arduino
|
// Here, when receiving any message on channel 4, the Arduino
|
||||||
// will blink a led and play back a note for 1 second.
|
// will blink a led and play back a note for 1 second.
|
||||||
|
|
||||||
|
MIDI_CREATE_DEFAULT_INSTANCE();
|
||||||
|
|
||||||
#define LED 13 // LED pin on Arduino Uno
|
#define LED 13 // LED pin on Arduino Uno
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,39 @@
|
||||||
#include <MIDI.h>
|
#include <MIDI.h>
|
||||||
|
|
||||||
|
MIDI_CREATE_DEFAULT_INSTANCE();
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// This function will be automatically called when a NoteOn is received.
|
// This function will be automatically called when a NoteOn is received.
|
||||||
// It must be a void-returning function with the correct parameters,
|
// It must be a void-returning function with the correct parameters,
|
||||||
// see documentation here:
|
// see documentation here:
|
||||||
// http://arduinomidilib.fortyseveneffects.com/a00022.html
|
// http://arduinomidilib.fortyseveneffects.com/a00022.html
|
||||||
|
|
||||||
void HandleNoteOn(byte channel, byte pitch, byte velocity)
|
void handleNoteOn(byte channel, byte pitch, byte velocity)
|
||||||
{
|
{
|
||||||
// Do whatever you want when you receive a Note On.
|
// Do whatever you want when a note is pressed.
|
||||||
|
|
||||||
if (velocity == 0)
|
|
||||||
{
|
|
||||||
// This acts like a NoteOff. You can ask the library to call the NoteOff
|
|
||||||
// callback when receiving null-velocity NoteOn messages.
|
|
||||||
// See MIDI_HANDLE_NULL_VELOCITY_NOTE_ON_AS_NOTE_OFF in midi_Settings.h
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to keep your callbacks short (no delays ect)
|
// Try to keep your callbacks short (no delays ect)
|
||||||
// otherwise it would slow down the loop() and have a bad impact
|
// otherwise it would slow down the loop() and have a bad impact
|
||||||
// on real-time performance.
|
// on real-time performance.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleNoteOff(byte channel, byte pitch, byte velocity)
|
||||||
|
{
|
||||||
|
// Do something when the note is released.
|
||||||
|
// Note that NoteOn messages with 0 velocity are interpreted as NoteOffs.
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// Connect the HandleNoteOn function to the library,
|
// Connect the handleNoteOn function to the library,
|
||||||
// so it is called upon reception of a NoteOn.
|
// so it is called upon reception of a NoteOn.
|
||||||
MIDI.setHandleNoteOn(HandleNoteOn); // Put only the name of the function
|
MIDI.setHandleNoteOn(handleNoteOn); // Put only the name of the function
|
||||||
|
|
||||||
|
// Do the same for NoteOffs
|
||||||
|
MIDI.setHandleNoteOff(handleNoteOff);
|
||||||
|
|
||||||
// Initiate MIDI communications, listen to all channels
|
// Initiate MIDI communications, listen to all channels
|
||||||
MIDI.begin(MIDI_CHANNEL_OMNI);
|
MIDI.begin(MIDI_CHANNEL_OMNI);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
#include <MIDI.h>
|
#include <MIDI.h>
|
||||||
|
|
||||||
|
MIDI_CREATE_DEFAULT_INSTANCE();
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// This example shows the old way of checking for input messages.
|
// This example shows the old way of checking for input messages.
|
||||||
// It's simpler to use the callbacks now, check out the dedicated example.
|
// It's simpler to use the callbacks now, check out the dedicated example.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#include "noteList.h"
|
#include "noteList.h"
|
||||||
#include "pitches.h"
|
#include "pitches.h"
|
||||||
|
|
||||||
|
MIDI_CREATE_DEFAULT_INSTANCE();
|
||||||
|
|
||||||
#ifdef ARDUINO_SAM_DUE // Due has no tone function (yet), overriden to prevent build errors.
|
#ifdef ARDUINO_SAM_DUE // Due has no tone function (yet), overriden to prevent build errors.
|
||||||
#define tone(...)
|
#define tone(...)
|
||||||
#define noTone(...)
|
#define noTone(...)
|
||||||
|
|
@ -18,12 +20,12 @@ MidiNoteList<sMaxNumNotes> midiNotes;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void handleGateChanged(bool inGateActive)
|
inline void handleGateChanged(bool inGateActive)
|
||||||
{
|
{
|
||||||
digitalWrite(sGatePin, inGateActive ? HIGH : LOW);
|
digitalWrite(sGatePin, inGateActive ? HIGH : LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pulseGate()
|
inline void pulseGate()
|
||||||
{
|
{
|
||||||
handleGateChanged(false);
|
handleGateChanged(false);
|
||||||
delay(1);
|
delay(1);
|
||||||
|
|
@ -32,7 +34,7 @@ void pulseGate()
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void handleNotesChanged()
|
void handleNotesChanged(bool isFirstNote = false)
|
||||||
{
|
{
|
||||||
if (midiNotes.empty())
|
if (midiNotes.empty())
|
||||||
{
|
{
|
||||||
|
|
@ -41,21 +43,35 @@ void handleNotesChanged()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Possible playing modes:
|
||||||
|
// Mono Low: use midiNotes.getLow
|
||||||
|
// Mono High: use midiNotes.getHigh
|
||||||
|
// Mono Last: use midiNotes.getLast
|
||||||
|
|
||||||
byte currentNote = 0;
|
byte currentNote = 0;
|
||||||
if (midiNotes.getTail(currentNote))
|
if (midiNotes.getLast(currentNote))
|
||||||
{
|
{
|
||||||
tone(sAudioOutPin, sNotePitches[currentNote]);
|
tone(sAudioOutPin, sNotePitches[currentNote]);
|
||||||
|
|
||||||
|
if (isFirstNote)
|
||||||
|
{
|
||||||
|
handleGateChanged(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
pulseGate(); // Retrigger envelopes. Remove for legato effect.
|
pulseGate(); // Retrigger envelopes. Remove for legato effect.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void handleNoteOn(byte inChannel, byte inNote, byte inVelocity)
|
void handleNoteOn(byte inChannel, byte inNote, byte inVelocity)
|
||||||
{
|
{
|
||||||
|
const bool firstNote = midiNotes.empty();
|
||||||
midiNotes.add(MidiNote(inNote, inVelocity));
|
midiNotes.add(MidiNote(inNote, inVelocity));
|
||||||
handleNotesChanged();
|
handleNotesChanged(firstNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleNoteOff(byte inChannel, byte inNote, byte inVelocity)
|
void handleNoteOff(byte inChannel, byte inNote, byte inVelocity)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
/*!
|
/*!
|
||||||
* \file synth-core_NoteList.h
|
* \file noteList.h
|
||||||
* \author Francois Best
|
* \author Francois Best
|
||||||
* \date 24/05/2013
|
* \date 24/05/2013
|
||||||
|
* \brief Linked list of notes, for Low, Last & High playing modes.
|
||||||
* \license GPL v3.0 - Copyright Forty Seven Effects 2013
|
* \license GPL v3.0 - Copyright Forty Seven Effects 2013
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
|
@ -65,7 +66,9 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline bool get(byte inIndex, byte& outPitch) const;
|
inline bool get(byte inIndex, byte& outPitch) const;
|
||||||
inline bool getTail(byte& outPitch) const;
|
inline bool getLast(byte& outPitch) const;
|
||||||
|
inline bool getHigh(byte& outPitch) const;
|
||||||
|
inline bool getLow(byte& outPitch) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline bool empty() const;
|
inline bool empty() const;
|
||||||
|
|
@ -145,8 +148,6 @@ inline typename MidiNoteList<Size>::Cell& MidiNoteList<Size>::Cell::operator= (c
|
||||||
template<byte Size>
|
template<byte Size>
|
||||||
inline MidiNoteList<Size>::MidiNoteList()
|
inline MidiNoteList<Size>::MidiNoteList()
|
||||||
{
|
{
|
||||||
// Check that size is a power of two
|
|
||||||
//AVR_STATIC_ASSERT(Size != 0 && !(Size & (Size - 1)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<byte Size>
|
template<byte Size>
|
||||||
|
|
@ -156,6 +157,10 @@ inline MidiNoteList<Size>::~MidiNoteList()
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*! \brief Add a note, sorting it by time.
|
||||||
|
Call this when receiving a NoteOn event. This will add the new note as the tail
|
||||||
|
of the list.
|
||||||
|
*/
|
||||||
template<byte Size>
|
template<byte Size>
|
||||||
inline void MidiNoteList<Size>::add(const MidiNote& inNote)
|
inline void MidiNoteList<Size>::add(const MidiNote& inNote)
|
||||||
{
|
{
|
||||||
|
|
@ -186,12 +191,15 @@ inline void MidiNoteList<Size>::add(const MidiNote& inNote)
|
||||||
print();
|
print();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Remove a note
|
||||||
|
Call this when receiving a NoteOff event.
|
||||||
|
*/
|
||||||
template<byte Size>
|
template<byte Size>
|
||||||
inline void MidiNoteList<Size>::remove(byte inPitch)
|
inline void MidiNoteList<Size>::remove(byte inPitch)
|
||||||
{
|
{
|
||||||
if (mHead != 0)
|
if (mTail != 0)
|
||||||
{
|
{
|
||||||
for (Cell* it = mHead; it != 0; it = it->next)
|
for (Cell* it = mTail; it != 0; it = it->prev)
|
||||||
{
|
{
|
||||||
if (it->note.pitch == inPitch)
|
if (it->note.pitch == inPitch)
|
||||||
{
|
{
|
||||||
|
|
@ -235,6 +243,9 @@ inline void MidiNoteList<Size>::remove(byte inPitch)
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*! \brief Get a note at an arbitrary position
|
||||||
|
This can be interesting for duo/multi/polyphony operations.
|
||||||
|
*/
|
||||||
template<byte Size>
|
template<byte Size>
|
||||||
inline bool MidiNoteList<Size>::get(byte inIndex, byte& outPitch) const
|
inline bool MidiNoteList<Size>::get(byte inIndex, byte& outPitch) const
|
||||||
{
|
{
|
||||||
|
|
@ -258,15 +269,75 @@ inline bool MidiNoteList<Size>::get(byte inIndex, byte& outPitch) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Get the last active note played
|
||||||
|
This implements the Mono Last playing mode.
|
||||||
|
*/
|
||||||
template<byte Size>
|
template<byte Size>
|
||||||
inline bool MidiNoteList<Size>::getTail(byte& outPitch) const
|
inline bool MidiNoteList<Size>::getLast(byte& outPitch) const
|
||||||
{
|
{
|
||||||
if (mTail)
|
if (!mTail)
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
outPitch = mTail->note.pitch;
|
outPitch = mTail->note.pitch;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Get the highest pitched active note
|
||||||
|
This implements the Mono High playing mode.
|
||||||
|
*/
|
||||||
|
template<byte Size>
|
||||||
|
inline bool MidiNoteList<Size>::getHigh(byte& outPitch) const
|
||||||
|
{
|
||||||
|
if (!mTail)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
outPitch = 0;
|
||||||
|
const Cell* it = mTail;
|
||||||
|
for (byte i = 0; i < mSize; ++i)
|
||||||
|
{
|
||||||
|
if (it->note.pitch > outPitch)
|
||||||
|
{
|
||||||
|
outPitch = it->note.pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it->prev)
|
||||||
|
{
|
||||||
|
it = it->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Get the lowest pitched active note
|
||||||
|
This implements the Mono Low playing mode.
|
||||||
|
*/
|
||||||
|
template<byte Size>
|
||||||
|
inline bool MidiNoteList<Size>::getLow(byte& outPitch) const
|
||||||
|
{
|
||||||
|
if (!mTail)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
outPitch = 0xff;
|
||||||
|
const Cell* it = mTail;
|
||||||
|
for (byte i = 0; i < mSize; ++i)
|
||||||
|
{
|
||||||
|
if (it->note.pitch < outPitch)
|
||||||
|
{
|
||||||
|
outPitch = it->note.pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it->prev)
|
||||||
|
{
|
||||||
|
it = it->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
@ -277,6 +348,8 @@ inline bool MidiNoteList<Size>::empty() const
|
||||||
return mSize == 0;
|
return mSize == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Get the number of active notes.
|
||||||
|
*/
|
||||||
template<byte Size>
|
template<byte Size>
|
||||||
inline byte MidiNoteList<Size>::size() const
|
inline byte MidiNoteList<Size>::size() const
|
||||||
{
|
{
|
||||||
|
|
@ -284,6 +357,7 @@ inline byte MidiNoteList<Size>::size() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
// Private implementations, for internal use only.
|
||||||
|
|
||||||
template<byte Size>
|
template<byte Size>
|
||||||
inline typename MidiNoteList<Size>::Cell* MidiNoteList<Size>::getFirstEmptyCell()
|
inline typename MidiNoteList<Size>::Cell* MidiNoteList<Size>::getFirstEmptyCell()
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
MIDI KEYWORD1
|
MIDI KEYWORD1
|
||||||
MIDI.h KEYWORD1
|
MIDI.h KEYWORD1
|
||||||
MidiInterface KEYWORD1
|
MidiInterface KEYWORD1
|
||||||
|
DefaultSettings KEYWORD1
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Methods and Functions (KEYWORD2)
|
# Methods and Functions (KEYWORD2)
|
||||||
|
|
@ -106,7 +107,6 @@ SameChannel LITERAL1
|
||||||
DifferentChannel LITERAL1
|
DifferentChannel LITERAL1
|
||||||
MIDI_CHANNEL_OMNI LITERAL1
|
MIDI_CHANNEL_OMNI LITERAL1
|
||||||
MIDI_CHANNEL_OFF LITERAL1
|
MIDI_CHANNEL_OFF LITERAL1
|
||||||
MIDI_BAUDRATE LITERAL1
|
|
||||||
MIDI_SYSEX_ARRAY_SIZE LITERAL1
|
|
||||||
MIDI_CREATE_INSTANCE LITERAL1
|
MIDI_CREATE_INSTANCE LITERAL1
|
||||||
MIDI_AUTO_INSTANCIATE LITERAL1
|
MIDI_CREATE_DEFAULT_INSTANCE LITERAL1
|
||||||
|
MIDI_CREATE_CUSTOM_INSTANCE LITERAL1
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ cd "`dirname "${0}"`"
|
||||||
root="${PWD}/.."
|
root="${PWD}/.."
|
||||||
build="$root/build/MIDI"
|
build="$root/build/MIDI"
|
||||||
|
|
||||||
echo root $root
|
echo "root: $root"
|
||||||
echo build $build
|
echo "build: $build"
|
||||||
|
|
||||||
# Create a temporary destination folder
|
# Create a temporary destination folder
|
||||||
mkdir -p "$build"
|
mkdir -p "$build"
|
||||||
|
|
@ -34,3 +34,7 @@ cp -r * "$build/examples"
|
||||||
# Generate package
|
# Generate package
|
||||||
cd "$build/.."
|
cd "$build/.."
|
||||||
zip -r Arduino_MIDI_Library.zip MIDI
|
zip -r Arduino_MIDI_Library.zip MIDI
|
||||||
|
|
||||||
|
# Generate doc
|
||||||
|
cd "$root/doc"
|
||||||
|
doxygen
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import sys
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import argparse
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from midi import *
|
from midi import *
|
||||||
from tester import *
|
from tester import *
|
||||||
|
|
@ -138,6 +139,29 @@ class ArduinoMidiLibrary:
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
info = "Validator script for the Arduino MIDI Library."
|
||||||
|
arg_parser = argparse.ArgumentParser(description = info)
|
||||||
|
|
||||||
|
arg_parser.add_argument('--compile', '-c',
|
||||||
|
action="store_true",
|
||||||
|
help="Test compilation of the example sketches")
|
||||||
|
|
||||||
|
arg_parser.add_argument('--runtime', '-r',
|
||||||
|
action="store_true",
|
||||||
|
help="Test runtime")
|
||||||
|
|
||||||
|
args = arg_parser.parse_args()
|
||||||
|
|
||||||
|
if args.compile:
|
||||||
|
lib = ArduinoMidiLibrary()
|
||||||
|
lib.install()
|
||||||
|
if lib.validate():
|
||||||
|
print('Compilation test passed')
|
||||||
|
else:
|
||||||
|
print('Compilation test failed')
|
||||||
|
|
||||||
|
if args.runtime:
|
||||||
midiInterface = MidiInterface()
|
midiInterface = MidiInterface()
|
||||||
tester = Tester(midiInterface)
|
tester = Tester(midiInterface)
|
||||||
midiInterface.listenerCallback = tester.handleMidiInput
|
midiInterface.listenerCallback = tester.handleMidiInput
|
||||||
|
|
@ -152,15 +176,6 @@ def main():
|
||||||
tester.checkThru([66, 127])
|
tester.checkThru([66, 127])
|
||||||
tester.checkThru([66, 0])
|
tester.checkThru([66, 0])
|
||||||
|
|
||||||
#lib = ArduinoMidiLibrary()
|
|
||||||
#lib.install()
|
|
||||||
#if lib.validate():
|
|
||||||
# print('Validation passed')
|
|
||||||
#else:
|
|
||||||
# print('Validation failed')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
||||||
23
src/MIDI.cpp
23
src/MIDI.cpp
|
|
@ -2,7 +2,7 @@
|
||||||
* @file MIDI.cpp
|
* @file MIDI.cpp
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino
|
* @brief MIDI Library for the Arduino
|
||||||
* @version 4.1
|
* @version 4.2
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
|
@ -25,27 +25,6 @@
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if !(MIDI_BUILD_INPUT) && !(MIDI_BUILD_OUTPUT)
|
|
||||||
# error To use MIDI, you need to enable at least input or output.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MIDI_BUILD_THRU && !(MIDI_BUILD_OUTPUT)
|
|
||||||
# error For thru to work, you need to enable output.
|
|
||||||
#endif
|
|
||||||
#if MIDI_BUILD_THRU && !(MIDI_BUILD_INPUT)
|
|
||||||
# error For thru to work, you need to enable input.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#if MIDI_AUTO_INSTANCIATE && defined(ARDUINO)
|
|
||||||
MIDI_CREATE_INSTANCE(MIDI_DEFAULT_SERIAL_CLASS,
|
|
||||||
MIDI_DEFAULT_SERIAL_PORT,
|
|
||||||
MIDI);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
BEGIN_MIDI_NAMESPACE
|
BEGIN_MIDI_NAMESPACE
|
||||||
|
|
||||||
/*! \brief Encode System Exclusive messages.
|
/*! \brief Encode System Exclusive messages.
|
||||||
|
|
|
||||||
80
src/MIDI.h
80
src/MIDI.h
|
|
@ -2,7 +2,7 @@
|
||||||
* @file MIDI.h
|
* @file MIDI.h
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino
|
* @brief MIDI Library for the Arduino
|
||||||
* @version 4.1
|
* @version 4.2
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
|
@ -23,12 +23,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "midi_Settings.h"
|
|
||||||
#include "midi_Defs.h"
|
#include "midi_Defs.h"
|
||||||
|
#include "midi_Settings.h"
|
||||||
#ifdef FSE_AVR
|
#include "midi_Message.h"
|
||||||
#include <ak47.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -40,12 +37,12 @@ the hardware interface, meaning you can use HardwareSerial, SoftwareSerial
|
||||||
or ak47's Uart classes. The only requirement is that the class implements
|
or ak47's Uart classes. The only requirement is that the class implements
|
||||||
the begin, read, write and available methods.
|
the begin, read, write and available methods.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings = DefaultSettings>
|
||||||
class MidiInterface
|
class MidiInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MidiInterface(SerialPort& inSerial);
|
inline MidiInterface(SerialPort& inSerial);
|
||||||
~MidiInterface();
|
inline ~MidiInterface();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void begin(Channel inChannel = 1);
|
void begin(Channel inChannel = 1);
|
||||||
|
|
@ -53,8 +50,6 @@ public:
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// MIDI Output
|
// MIDI Output
|
||||||
|
|
||||||
#if MIDI_BUILD_OUTPUT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline void sendNoteOn(DataByte inNoteNumber,
|
inline void sendNoteOn(DataByte inNoteNumber,
|
||||||
DataByte inVelocity,
|
DataByte inVelocity,
|
||||||
|
|
@ -100,17 +95,9 @@ public:
|
||||||
DataByte inData2,
|
DataByte inData2,
|
||||||
Channel inChannel);
|
Channel inChannel);
|
||||||
|
|
||||||
private:
|
|
||||||
inline StatusByte getStatus(MidiType inType,
|
|
||||||
Channel inChannel) const;
|
|
||||||
|
|
||||||
#endif // MIDI_BUILD_OUTPUT
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// MIDI Input
|
// MIDI Input
|
||||||
|
|
||||||
#if MIDI_BUILD_INPUT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline bool read();
|
inline bool read();
|
||||||
inline bool read(Channel inChannel);
|
inline bool read(Channel inChannel);
|
||||||
|
|
@ -133,25 +120,10 @@ public:
|
||||||
static inline Channel getChannelFromStatusByte(byte inStatus);
|
static inline Channel getChannelFromStatusByte(byte inStatus);
|
||||||
static inline bool isChannelMessage(MidiType inType);
|
static inline bool isChannelMessage(MidiType inType);
|
||||||
|
|
||||||
private:
|
|
||||||
bool parse();
|
|
||||||
inline void handleNullVelocityNoteOnAsNoteOff();
|
|
||||||
inline bool inputFilter(Channel inChannel);
|
|
||||||
inline void resetInput();
|
|
||||||
|
|
||||||
private:
|
|
||||||
StatusByte mRunningStatus_RX;
|
|
||||||
Channel mInputChannel;
|
|
||||||
byte mPendingMessage[3];
|
|
||||||
unsigned mPendingMessageExpectedLenght;
|
|
||||||
unsigned mPendingMessageIndex;
|
|
||||||
Message mMessage;
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Input Callbacks
|
// Input Callbacks
|
||||||
|
|
||||||
#if MIDI_USE_CALLBACKS
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline void setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity));
|
inline void setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity));
|
||||||
inline void setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity));
|
inline void setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity));
|
||||||
|
|
@ -160,7 +132,7 @@ public:
|
||||||
inline void setHandleProgramChange(void (*fptr)(byte channel, byte number));
|
inline void setHandleProgramChange(void (*fptr)(byte channel, byte number));
|
||||||
inline void setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure));
|
inline void setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure));
|
||||||
inline void setHandlePitchBend(void (*fptr)(byte channel, int bend));
|
inline void setHandlePitchBend(void (*fptr)(byte channel, int bend));
|
||||||
inline void setHandleSystemExclusive(void (*fptr)(byte * array, byte size));
|
inline void setHandleSystemExclusive(void (*fptr)(byte * array, unsigned size));
|
||||||
inline void setHandleTimeCodeQuarterFrame(void (*fptr)(byte data));
|
inline void setHandleTimeCodeQuarterFrame(void (*fptr)(byte data));
|
||||||
inline void setHandleSongPosition(void (*fptr)(unsigned beats));
|
inline void setHandleSongPosition(void (*fptr)(unsigned beats));
|
||||||
inline void setHandleSongSelect(void (*fptr)(byte songnumber));
|
inline void setHandleSongSelect(void (*fptr)(byte songnumber));
|
||||||
|
|
@ -184,7 +156,7 @@ private:
|
||||||
void (*mProgramChangeCallback)(byte channel, byte);
|
void (*mProgramChangeCallback)(byte channel, byte);
|
||||||
void (*mAfterTouchChannelCallback)(byte channel, byte);
|
void (*mAfterTouchChannelCallback)(byte channel, byte);
|
||||||
void (*mPitchBendCallback)(byte channel, int);
|
void (*mPitchBendCallback)(byte channel, int);
|
||||||
void (*mSystemExclusiveCallback)(byte * array, byte size);
|
void (*mSystemExclusiveCallback)(byte * array, unsigned size);
|
||||||
void (*mTimeCodeQuarterFrameCallback)(byte data);
|
void (*mTimeCodeQuarterFrameCallback)(byte data);
|
||||||
void (*mSongPositionCallback)(unsigned beats);
|
void (*mSongPositionCallback)(unsigned beats);
|
||||||
void (*mSongSelectCallback)(byte songnumber);
|
void (*mSongSelectCallback)(byte songnumber);
|
||||||
|
|
@ -196,14 +168,9 @@ private:
|
||||||
void (*mActiveSensingCallback)(void);
|
void (*mActiveSensingCallback)(void);
|
||||||
void (*mSystemResetCallback)(void);
|
void (*mSystemResetCallback)(void);
|
||||||
|
|
||||||
#endif // MIDI_USE_CALLBACKS
|
|
||||||
#endif // MIDI_BUILD_INPUT
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// MIDI Soft Thru
|
// MIDI Soft Thru
|
||||||
|
|
||||||
#if MIDI_BUILD_THRU
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline MidiFilterMode getFilterMode() const;
|
inline MidiFilterMode getFilterMode() const;
|
||||||
inline bool getThruState() const;
|
inline bool getThruState() const;
|
||||||
|
|
@ -212,21 +179,34 @@ public:
|
||||||
inline void turnThruOff();
|
inline void turnThruOff();
|
||||||
inline void setThruFilterMode(MidiFilterMode inThruFilterMode);
|
inline void setThruFilterMode(MidiFilterMode inThruFilterMode);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void thruFilter(byte inChannel);
|
void thruFilter(byte inChannel);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool parse();
|
||||||
|
inline void handleNullVelocityNoteOnAsNoteOff();
|
||||||
|
inline bool inputFilter(Channel inChannel);
|
||||||
|
inline void resetInput();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mThruActivated : 1;
|
bool mThruActivated : 1;
|
||||||
MidiFilterMode mThruFilterMode : 7;
|
MidiFilterMode mThruFilterMode : 7;
|
||||||
|
|
||||||
#endif // MIDI_BUILD_THRU
|
|
||||||
|
|
||||||
|
|
||||||
#if MIDI_USE_RUNNING_STATUS
|
|
||||||
private:
|
private:
|
||||||
|
typedef Message<Settings::SysExMaxSize> MidiMessage;
|
||||||
|
|
||||||
|
private:
|
||||||
|
StatusByte mRunningStatus_RX;
|
||||||
StatusByte mRunningStatus_TX;
|
StatusByte mRunningStatus_TX;
|
||||||
#endif
|
Channel mInputChannel;
|
||||||
|
byte mPendingMessage[3];
|
||||||
|
unsigned mPendingMessageExpectedLenght;
|
||||||
|
unsigned mPendingMessageIndex;
|
||||||
|
MidiMessage mMessage;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline StatusByte getStatus(MidiType inType,
|
||||||
|
Channel inChannel) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SerialPort& mSerial;
|
SerialPort& mSerial;
|
||||||
|
|
@ -241,10 +221,4 @@ END_MIDI_NAMESPACE
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if MIDI_AUTO_INSTANCIATE && defined(ARDUINO)
|
|
||||||
extern MIDI_NAMESPACE::MidiInterface<MIDI_DEFAULT_SERIAL_CLASS> MIDI;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include "MIDI.hpp"
|
#include "MIDI.hpp"
|
||||||
|
|
|
||||||
420
src/MIDI.hpp
420
src/MIDI.hpp
|
|
@ -1,8 +1,8 @@
|
||||||
/*!
|
/*!
|
||||||
* @file midi_Inline.hpp
|
* @file MIDI.hpp
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino - Inline implementations
|
* @brief MIDI Library for the Arduino - Inline implementations
|
||||||
* @version 4.1
|
* @version 4.2
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
|
@ -26,11 +26,10 @@
|
||||||
BEGIN_MIDI_NAMESPACE
|
BEGIN_MIDI_NAMESPACE
|
||||||
|
|
||||||
/// \brief Constructor for MidiInterface.
|
/// \brief Constructor for MidiInterface.
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
MidiInterface<SerialPort>::MidiInterface(SerialPort& inSerial)
|
inline MidiInterface<SerialPort, Settings>::MidiInterface(SerialPort& inSerial)
|
||||||
: mSerial(inSerial)
|
: mSerial(inSerial)
|
||||||
{
|
{
|
||||||
#if MIDI_BUILD_INPUT && MIDI_USE_CALLBACKS
|
|
||||||
mNoteOffCallback = 0;
|
mNoteOffCallback = 0;
|
||||||
mNoteOnCallback = 0;
|
mNoteOnCallback = 0;
|
||||||
mAfterTouchPolyCallback = 0;
|
mAfterTouchPolyCallback = 0;
|
||||||
|
|
@ -49,15 +48,14 @@ MidiInterface<SerialPort>::MidiInterface(SerialPort& inSerial)
|
||||||
mStopCallback = 0;
|
mStopCallback = 0;
|
||||||
mActiveSensingCallback = 0;
|
mActiveSensingCallback = 0;
|
||||||
mSystemResetCallback = 0;
|
mSystemResetCallback = 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Destructor for MidiInterface.
|
/*! \brief Destructor for MidiInterface.
|
||||||
|
|
||||||
This is not really useful for the Arduino, as it is never called...
|
This is not really useful for the Arduino, as it is never called...
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
MidiInterface<SerialPort>::~MidiInterface()
|
inline MidiInterface<SerialPort, Settings>::~MidiInterface()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,27 +67,20 @@ MidiInterface<SerialPort>::~MidiInterface()
|
||||||
- Input channel set to 1 if no value is specified
|
- Input channel set to 1 if no value is specified
|
||||||
- Full thru mirroring
|
- Full thru mirroring
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::begin(Channel inChannel)
|
void MidiInterface<SerialPort, Settings>::begin(Channel inChannel)
|
||||||
{
|
{
|
||||||
// Initialise the Serial port
|
// Initialise the Serial port
|
||||||
#if defined(ARDUINO)
|
#if defined(FSE_AVR)
|
||||||
mSerial.begin(MIDI_BAUDRATE);
|
mSerial. template open<Settings::BaudRate>();
|
||||||
#elif defined(FSE_AVR)
|
#else
|
||||||
mSerial. template open<MIDI_BAUDRATE>();
|
mSerial.begin(Settings::BaudRate);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MIDI_BUILD_OUTPUT && MIDI_USE_RUNNING_STATUS
|
|
||||||
|
|
||||||
mRunningStatus_TX = InvalidType;
|
|
||||||
|
|
||||||
#endif // MIDI_BUILD_OUTPUT && MIDI_USE_RUNNING_STATUS
|
|
||||||
|
|
||||||
|
|
||||||
#if MIDI_BUILD_INPUT
|
|
||||||
|
|
||||||
mInputChannel = inChannel;
|
mInputChannel = inChannel;
|
||||||
|
mRunningStatus_TX = InvalidType;
|
||||||
mRunningStatus_RX = InvalidType;
|
mRunningStatus_RX = InvalidType;
|
||||||
|
|
||||||
mPendingMessageIndex = 0;
|
mPendingMessageIndex = 0;
|
||||||
mPendingMessageExpectedLenght = 0;
|
mPendingMessageExpectedLenght = 0;
|
||||||
|
|
||||||
|
|
@ -99,25 +90,14 @@ void MidiInterface<SerialPort>::begin(Channel inChannel)
|
||||||
mMessage.data1 = 0;
|
mMessage.data1 = 0;
|
||||||
mMessage.data2 = 0;
|
mMessage.data2 = 0;
|
||||||
|
|
||||||
#endif // MIDI_BUILD_INPUT
|
|
||||||
|
|
||||||
|
|
||||||
#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU) // Thru
|
|
||||||
|
|
||||||
mThruFilterMode = Full;
|
mThruFilterMode = Full;
|
||||||
mThruActivated = true;
|
mThruActivated = true;
|
||||||
|
|
||||||
#endif // Thru
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Output
|
// Output
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if MIDI_BUILD_OUTPUT
|
|
||||||
|
|
||||||
/*! \addtogroup output
|
/*! \addtogroup output
|
||||||
@{
|
@{
|
||||||
*/
|
*/
|
||||||
|
|
@ -133,8 +113,8 @@ void MidiInterface<SerialPort>::begin(Channel inChannel)
|
||||||
This is an internal method, use it only if you need to send raw data
|
This is an internal method, use it only if you need to send raw data
|
||||||
from your code, at your own risks.
|
from your code, at your own risks.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::send(MidiType inType,
|
void MidiInterface<SerialPort, Settings>::send(MidiType inType,
|
||||||
DataByte inData1,
|
DataByte inData1,
|
||||||
DataByte inData2,
|
DataByte inData2,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
|
|
@ -142,13 +122,12 @@ void MidiInterface<SerialPort>::send(MidiType inType,
|
||||||
// Then test if channel is valid
|
// Then test if channel is valid
|
||||||
if (inChannel >= MIDI_CHANNEL_OFF ||
|
if (inChannel >= MIDI_CHANNEL_OFF ||
|
||||||
inChannel == MIDI_CHANNEL_OMNI ||
|
inChannel == MIDI_CHANNEL_OMNI ||
|
||||||
inType < NoteOff)
|
inType < 0x80)
|
||||||
|
{
|
||||||
|
if (Settings::UseRunningStatus)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if MIDI_USE_RUNNING_STATUS
|
|
||||||
mRunningStatus_TX = InvalidType;
|
mRunningStatus_TX = InvalidType;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
return; // Don't send anything
|
return; // Don't send anything
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,28 +139,32 @@ void MidiInterface<SerialPort>::send(MidiType inType,
|
||||||
|
|
||||||
const StatusByte status = getStatus(inType, inChannel);
|
const StatusByte status = getStatus(inType, inChannel);
|
||||||
|
|
||||||
#if MIDI_USE_RUNNING_STATUS
|
if (Settings::UseRunningStatus)
|
||||||
// Check Running Status
|
{
|
||||||
if (mRunningStatus_TX != status)
|
if (mRunningStatus_TX != status)
|
||||||
{
|
{
|
||||||
// New message, memorise and send header
|
// New message, memorise and send header
|
||||||
mRunningStatus_TX = status;
|
mRunningStatus_TX = status;
|
||||||
mSerial.write(mRunningStatus_TX);
|
mSerial.write(mRunningStatus_TX);
|
||||||
}
|
}
|
||||||
#else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Don't care about running status, send the status byte.
|
// Don't care about running status, send the status byte.
|
||||||
mSerial.write(status);
|
mSerial.write(status);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
// Then send data
|
// Then send data
|
||||||
mSerial.write(inData1);
|
mSerial.write(inData1);
|
||||||
if (inType != ProgramChange && inType != AfterTouchChannel)
|
if (inType != ProgramChange && inType != AfterTouchChannel)
|
||||||
|
{
|
||||||
mSerial.write(inData2);
|
mSerial.write(inData2);
|
||||||
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else if (inType >= TuneRequest && inType <= SystemReset)
|
else if (inType >= TuneRequest && inType <= SystemReset)
|
||||||
|
{
|
||||||
sendRealTime(inType); // System Real-time and 1 byte.
|
sendRealTime(inType); // System Real-time and 1 byte.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
@ -195,8 +178,8 @@ void MidiInterface<SerialPort>::send(MidiType inType,
|
||||||
Take a look at the values, names and frequencies of notes here:
|
Take a look at the values, names and frequencies of notes here:
|
||||||
http://www.phys.unsw.edu.au/jw/notes.html
|
http://www.phys.unsw.edu.au/jw/notes.html
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendNoteOn(DataByte inNoteNumber,
|
void MidiInterface<SerialPort, Settings>::sendNoteOn(DataByte inNoteNumber,
|
||||||
DataByte inVelocity,
|
DataByte inVelocity,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
|
|
@ -210,12 +193,12 @@ void MidiInterface<SerialPort>::sendNoteOn(DataByte inNoteNumber,
|
||||||
|
|
||||||
Note: you can send NoteOn with zero velocity to make a NoteOff, this is based
|
Note: you can send NoteOn with zero velocity to make a NoteOff, this is based
|
||||||
on the Running Status principle, to avoid sending status messages and thus
|
on the Running Status principle, to avoid sending status messages and thus
|
||||||
sending only NoteOn data. This method will always send a real NoteOff message.
|
sending only NoteOn data. sendNoteOff will always send a real NoteOff message.
|
||||||
Take a look at the values, names and frequencies of notes here:
|
Take a look at the values, names and frequencies of notes here:
|
||||||
http://www.phys.unsw.edu.au/jw/notes.html
|
http://www.phys.unsw.edu.au/jw/notes.html
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendNoteOff(DataByte inNoteNumber,
|
void MidiInterface<SerialPort, Settings>::sendNoteOff(DataByte inNoteNumber,
|
||||||
DataByte inVelocity,
|
DataByte inVelocity,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
|
|
@ -226,8 +209,8 @@ void MidiInterface<SerialPort>::sendNoteOff(DataByte inNoteNumber,
|
||||||
\param inProgramNumber The Program to select (0 to 127).
|
\param inProgramNumber The Program to select (0 to 127).
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendProgramChange(DataByte inProgramNumber,
|
void MidiInterface<SerialPort, Settings>::sendProgramChange(DataByte inProgramNumber,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
send(ProgramChange, inProgramNumber, 0, inChannel);
|
send(ProgramChange, inProgramNumber, 0, inChannel);
|
||||||
|
|
@ -239,8 +222,8 @@ void MidiInterface<SerialPort>::sendProgramChange(DataByte inProgramNumber,
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
@see MidiControlChangeNumber
|
@see MidiControlChangeNumber
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendControlChange(DataByte inControlNumber,
|
void MidiInterface<SerialPort, Settings>::sendControlChange(DataByte inControlNumber,
|
||||||
DataByte inControlValue,
|
DataByte inControlValue,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
|
|
@ -252,8 +235,8 @@ void MidiInterface<SerialPort>::sendControlChange(DataByte inControlNumber,
|
||||||
\param inPressure The amount of AfterTouch to apply (0 to 127).
|
\param inPressure The amount of AfterTouch to apply (0 to 127).
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendPolyPressure(DataByte inNoteNumber,
|
void MidiInterface<SerialPort, Settings>::sendPolyPressure(DataByte inNoteNumber,
|
||||||
DataByte inPressure,
|
DataByte inPressure,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
|
|
@ -264,8 +247,8 @@ void MidiInterface<SerialPort>::sendPolyPressure(DataByte inNoteNumber,
|
||||||
\param inPressure The amount of AfterTouch to apply to all notes.
|
\param inPressure The amount of AfterTouch to apply to all notes.
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendAfterTouch(DataByte inPressure,
|
void MidiInterface<SerialPort, Settings>::sendAfterTouch(DataByte inPressure,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
send(AfterTouchChannel, inPressure, 0, inChannel);
|
send(AfterTouchChannel, inPressure, 0, inChannel);
|
||||||
|
|
@ -277,8 +260,8 @@ void MidiInterface<SerialPort>::sendAfterTouch(DataByte inPressure,
|
||||||
center value is 0.
|
center value is 0.
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendPitchBend(int inPitchValue,
|
void MidiInterface<SerialPort, Settings>::sendPitchBend(int inPitchValue,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
const unsigned bend = inPitchValue - MIDI_PITCHBEND_MIN;
|
const unsigned bend = inPitchValue - MIDI_PITCHBEND_MIN;
|
||||||
|
|
@ -292,11 +275,11 @@ void MidiInterface<SerialPort>::sendPitchBend(int inPitchValue,
|
||||||
and +1.0f (max upwards bend), center value is 0.0f.
|
and +1.0f (max upwards bend), center value is 0.0f.
|
||||||
\param inChannel The channel on which the message will be sent (1 to 16).
|
\param inChannel The channel on which the message will be sent (1 to 16).
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendPitchBend(double inPitchValue,
|
void MidiInterface<SerialPort, Settings>::sendPitchBend(double inPitchValue,
|
||||||
Channel inChannel)
|
Channel inChannel)
|
||||||
{
|
{
|
||||||
const int value = inPitchValue * MIDI_PITCHBEND_MAX;
|
const int value = inPitchValue * MIDI_PITCHBEND_MAX * Settings::Toto;
|
||||||
sendPitchBend(value, inChannel);
|
sendPitchBend(value, inChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,29 +292,32 @@ void MidiInterface<SerialPort>::sendPitchBend(double inPitchValue,
|
||||||
default value for ArrayContainsBoundaries is set to 'false' for compatibility
|
default value for ArrayContainsBoundaries is set to 'false' for compatibility
|
||||||
with previous versions of the library.
|
with previous versions of the library.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendSysEx(unsigned inLength,
|
void MidiInterface<SerialPort, Settings>::sendSysEx(unsigned inLength,
|
||||||
const byte* inArray,
|
const byte* inArray,
|
||||||
bool inArrayContainsBoundaries)
|
bool inArrayContainsBoundaries)
|
||||||
{
|
{
|
||||||
if (inArrayContainsBoundaries == false)
|
const bool writeBeginEndBytes = !inArrayContainsBoundaries;
|
||||||
|
|
||||||
|
if (writeBeginEndBytes)
|
||||||
{
|
{
|
||||||
mSerial.write(0xf0);
|
mSerial.write(0xf0);
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < inLength; ++i)
|
for (unsigned i = 0; i < inLength; ++i)
|
||||||
|
{
|
||||||
mSerial.write(inArray[i]);
|
mSerial.write(inArray[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeBeginEndBytes)
|
||||||
|
{
|
||||||
mSerial.write(0xf7);
|
mSerial.write(0xf7);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < inLength; ++i)
|
|
||||||
mSerial.write(inArray[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MIDI_USE_RUNNING_STATUS
|
if (Settings::UseRunningStatus)
|
||||||
|
{
|
||||||
mRunningStatus_TX = InvalidType;
|
mRunningStatus_TX = InvalidType;
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Tune Request message.
|
/*! \brief Send a Tune Request message.
|
||||||
|
|
@ -339,8 +325,8 @@ void MidiInterface<SerialPort>::sendSysEx(unsigned inLength,
|
||||||
When a MIDI unit receives this message,
|
When a MIDI unit receives this message,
|
||||||
it should tune its oscillators (if equipped with any).
|
it should tune its oscillators (if equipped with any).
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendTuneRequest()
|
void MidiInterface<SerialPort, Settings>::sendTuneRequest()
|
||||||
{
|
{
|
||||||
sendRealTime(TuneRequest);
|
sendRealTime(TuneRequest);
|
||||||
}
|
}
|
||||||
|
|
@ -351,8 +337,8 @@ void MidiInterface<SerialPort>::sendTuneRequest()
|
||||||
\param inValuesNibble MTC data
|
\param inValuesNibble MTC data
|
||||||
See MIDI Specification for more information.
|
See MIDI Specification for more information.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
|
void MidiInterface<SerialPort, Settings>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
|
||||||
DataByte inValuesNibble)
|
DataByte inValuesNibble)
|
||||||
{
|
{
|
||||||
const byte data = (((inTypeNibble & 0x07) << 4) | (inValuesNibble & 0x0f));
|
const byte data = (((inTypeNibble & 0x07) << 4) | (inValuesNibble & 0x0f));
|
||||||
|
|
@ -365,42 +351,45 @@ void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
|
||||||
\param inData if you want to encode directly the nibbles in your program,
|
\param inData if you want to encode directly the nibbles in your program,
|
||||||
you can send the byte here.
|
you can send the byte here.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inData)
|
void MidiInterface<SerialPort, Settings>::sendTimeCodeQuarterFrame(DataByte inData)
|
||||||
{
|
{
|
||||||
mSerial.write((byte)TimeCodeQuarterFrame);
|
mSerial.write((byte)TimeCodeQuarterFrame);
|
||||||
mSerial.write(inData);
|
mSerial.write(inData);
|
||||||
|
|
||||||
#if MIDI_USE_RUNNING_STATUS
|
if (Settings::UseRunningStatus)
|
||||||
|
{
|
||||||
mRunningStatus_TX = InvalidType;
|
mRunningStatus_TX = InvalidType;
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Song Position Pointer message.
|
/*! \brief Send a Song Position Pointer message.
|
||||||
\param inBeats The number of beats since the start of the song.
|
\param inBeats The number of beats since the start of the song.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendSongPosition(unsigned inBeats)
|
void MidiInterface<SerialPort, Settings>::sendSongPosition(unsigned inBeats)
|
||||||
{
|
{
|
||||||
mSerial.write((byte)SongPosition);
|
mSerial.write((byte)SongPosition);
|
||||||
mSerial.write(inBeats & 0x7f);
|
mSerial.write(inBeats & 0x7f);
|
||||||
mSerial.write((inBeats >> 7) & 0x7f);
|
mSerial.write((inBeats >> 7) & 0x7f);
|
||||||
|
|
||||||
#if MIDI_USE_RUNNING_STATUS
|
if (Settings::UseRunningStatus)
|
||||||
|
{
|
||||||
mRunningStatus_TX = InvalidType;
|
mRunningStatus_TX = InvalidType;
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Song Select message */
|
/*! \brief Send a Song Select message */
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendSongSelect(DataByte inSongNumber)
|
void MidiInterface<SerialPort, Settings>::sendSongSelect(DataByte inSongNumber)
|
||||||
{
|
{
|
||||||
mSerial.write((byte)SongSelect);
|
mSerial.write((byte)SongSelect);
|
||||||
mSerial.write(inSongNumber & 0x7f);
|
mSerial.write(inSongNumber & 0x7f);
|
||||||
|
|
||||||
#if MIDI_USE_RUNNING_STATUS
|
if (Settings::UseRunningStatus)
|
||||||
|
{
|
||||||
mRunningStatus_TX = InvalidType;
|
mRunningStatus_TX = InvalidType;
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Send a Real Time (one byte) message.
|
/*! \brief Send a Real Time (one byte) message.
|
||||||
|
|
@ -410,8 +399,8 @@ void MidiInterface<SerialPort>::sendSongSelect(DataByte inSongNumber)
|
||||||
You can also send a Tune Request with this method.
|
You can also send a Tune Request with this method.
|
||||||
@see MidiType
|
@see MidiType
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::sendRealTime(MidiType inType)
|
void MidiInterface<SerialPort, Settings>::sendRealTime(MidiType inType)
|
||||||
{
|
{
|
||||||
switch (inType)
|
switch (inType)
|
||||||
{
|
{
|
||||||
|
|
@ -432,31 +421,27 @@ void MidiInterface<SerialPort>::sendRealTime(MidiType inType)
|
||||||
// Do not cancel Running Status for real-time messages as they can be
|
// Do not cancel Running Status for real-time messages as they can be
|
||||||
// interleaved within any message. Though, TuneRequest can be sent here,
|
// interleaved within any message. Though, TuneRequest can be sent here,
|
||||||
// and as it is a System Common message, it must reset Running Status.
|
// and as it is a System Common message, it must reset Running Status.
|
||||||
#if MIDI_USE_RUNNING_STATUS
|
if (Settings::UseRunningStatus && inType == TuneRequest)
|
||||||
if (inType == TuneRequest) mRunningStatus_TX = InvalidType;
|
{
|
||||||
#endif
|
mRunningStatus_TX = InvalidType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! @} */ // End of doc group MIDI Output
|
/*! @} */ // End of doc group MIDI Output
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
StatusByte MidiInterface<SerialPort>::getStatus(MidiType inType,
|
StatusByte MidiInterface<SerialPort, Settings>::getStatus(MidiType inType,
|
||||||
Channel inChannel) const
|
Channel inChannel) const
|
||||||
{
|
{
|
||||||
return ((byte)inType | ((inChannel - 1) & 0x0f));
|
return ((byte)inType | ((inChannel - 1) & 0x0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MIDI_BUILD_OUTPUT
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Input
|
// Input
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if MIDI_BUILD_INPUT
|
|
||||||
|
|
||||||
/*! \addtogroup input
|
/*! \addtogroup input
|
||||||
@{
|
@{
|
||||||
*/
|
*/
|
||||||
|
|
@ -469,45 +454,41 @@ StatusByte MidiInterface<SerialPort>::getStatus(MidiType inType,
|
||||||
it is sent back on the MIDI output.
|
it is sent back on the MIDI output.
|
||||||
@see see setInputChannel()
|
@see see setInputChannel()
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
inline bool MidiInterface<SerialPort>::read()
|
inline bool MidiInterface<SerialPort, Settings>::read()
|
||||||
{
|
{
|
||||||
return read(mInputChannel);
|
return read(mInputChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Read messages on a specified channel.
|
/*! \brief Read messages on a specified channel.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
inline bool MidiInterface<SerialPort>::read(Channel inChannel)
|
inline bool MidiInterface<SerialPort, Settings>::read(Channel inChannel)
|
||||||
{
|
{
|
||||||
if (inChannel >= MIDI_CHANNEL_OFF)
|
if (inChannel >= MIDI_CHANNEL_OFF)
|
||||||
return false; // MIDI Input disabled.
|
return false; // MIDI Input disabled.
|
||||||
|
|
||||||
if (parse())
|
if (!parse())
|
||||||
{
|
|
||||||
handleNullVelocityNoteOnAsNoteOff();
|
|
||||||
if (inputFilter(inChannel))
|
|
||||||
{
|
|
||||||
|
|
||||||
#if (MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU)
|
|
||||||
thruFilter(inChannel);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MIDI_USE_CALLBACKS
|
|
||||||
launchCallback();
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
handleNullVelocityNoteOnAsNoteOff();
|
||||||
|
const bool channelMatch = inputFilter(inChannel);
|
||||||
|
|
||||||
|
if (channelMatch)
|
||||||
|
{
|
||||||
|
launchCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
thruFilter(inChannel);
|
||||||
|
|
||||||
|
return channelMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Private method: MIDI parser
|
// Private method: MIDI parser
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
bool MidiInterface<SerialPort>::parse()
|
bool MidiInterface<SerialPort, Settings>::parse()
|
||||||
{
|
{
|
||||||
if (mSerial.available() == 0)
|
if (mSerial.available() == 0)
|
||||||
// No data available.
|
// No data available.
|
||||||
|
|
@ -595,8 +576,8 @@ bool MidiInterface<SerialPort>::parse()
|
||||||
|
|
||||||
case SystemExclusive:
|
case SystemExclusive:
|
||||||
// The message can be any lenght
|
// The message can be any lenght
|
||||||
// between 3 and MIDI_SYSEX_ARRAY_SIZE bytes
|
// between 3 and MidiMessage::sSysExMaxSize bytes
|
||||||
mPendingMessageExpectedLenght = MIDI_SYSEX_ARRAY_SIZE;
|
mPendingMessageExpectedLenght = MidiMessage::sSysExMaxSize;
|
||||||
mRunningStatus_RX = InvalidType;
|
mRunningStatus_RX = InvalidType;
|
||||||
mMessage.sysexArray[0] = SystemExclusive;
|
mMessage.sysexArray[0] = SystemExclusive;
|
||||||
break;
|
break;
|
||||||
|
|
@ -633,15 +614,17 @@ bool MidiInterface<SerialPort>::parse()
|
||||||
mPendingMessageIndex++;
|
mPendingMessageIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_1BYTE_PARSING
|
if (Settings::Use1ByteParsing)
|
||||||
|
{
|
||||||
// Message is not complete.
|
// Message is not complete.
|
||||||
return false;
|
return false;
|
||||||
#else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Call the parser recursively
|
// Call the parser recursively
|
||||||
// to parse the rest of the message.
|
// to parse the rest of the message.
|
||||||
return parse();
|
return parse();
|
||||||
#endif
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -684,8 +667,8 @@ bool MidiInterface<SerialPort>::parse()
|
||||||
mMessage.type = SystemExclusive;
|
mMessage.type = SystemExclusive;
|
||||||
|
|
||||||
// Get length
|
// Get length
|
||||||
mMessage.data1 = mPendingMessageIndex & 0xff;
|
mMessage.data1 = mPendingMessageIndex & 0xff; // LSB
|
||||||
mMessage.data2 = mPendingMessageIndex >> 8;
|
mMessage.data2 = mPendingMessageIndex >> 8; // MSB
|
||||||
mMessage.channel = 0;
|
mMessage.channel = 0;
|
||||||
mMessage.valid = true;
|
mMessage.valid = true;
|
||||||
|
|
||||||
|
|
@ -716,7 +699,7 @@ bool MidiInterface<SerialPort>::parse()
|
||||||
{
|
{
|
||||||
// "FML" case: fall down here with an overflown SysEx..
|
// "FML" case: fall down here with an overflown SysEx..
|
||||||
// This means we received the last possible data byte that can fit
|
// This means we received the last possible data byte that can fit
|
||||||
// the buffer. If this happens, try increasing MIDI_SYSEX_ARRAY_SIZE.
|
// the buffer. If this happens, try increasing MidiMessage::sSysExMaxSize.
|
||||||
if (mPendingMessage[0] == SystemExclusive)
|
if (mPendingMessage[0] == SystemExclusive)
|
||||||
{
|
{
|
||||||
resetInput();
|
resetInput();
|
||||||
|
|
@ -770,33 +753,34 @@ bool MidiInterface<SerialPort>::parse()
|
||||||
// Then update the index of the pending message.
|
// Then update the index of the pending message.
|
||||||
mPendingMessageIndex++;
|
mPendingMessageIndex++;
|
||||||
|
|
||||||
#if USE_1BYTE_PARSING
|
if (Settings::Use1ByteParsing)
|
||||||
|
{
|
||||||
// Message is not complete.
|
// Message is not complete.
|
||||||
return false;
|
return false;
|
||||||
#else
|
}
|
||||||
// Call the parser recursively
|
else
|
||||||
// to parse the rest of the message.
|
{
|
||||||
|
// Call the parser recursively to parse the rest of the message.
|
||||||
return parse();
|
return parse();
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private method, see midi_Settings.h for documentation
|
// Private method, see midi_Settings.h for documentation
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
inline void MidiInterface<SerialPort>::handleNullVelocityNoteOnAsNoteOff()
|
inline void MidiInterface<SerialPort, Settings>::handleNullVelocityNoteOnAsNoteOff()
|
||||||
{
|
{
|
||||||
#if MIDI_HANDLE_NULL_VELOCITY_NOTE_ON_AS_NOTE_OFF
|
if (Settings::HandleNullVelocityNoteOnAsNoteOff &&
|
||||||
if (getType() == NoteOn && getData2() == 0)
|
getType() == NoteOn && getData2() == 0)
|
||||||
{
|
{
|
||||||
mMessage.type = NoteOff;
|
mMessage.type = NoteOff;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private method: check if the received message is on the listened channel
|
// Private method: check if the received message is on the listened channel
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
inline bool MidiInterface<SerialPort>::inputFilter(Channel inChannel)
|
inline bool MidiInterface<SerialPort, Settings>::inputFilter(Channel inChannel)
|
||||||
{
|
{
|
||||||
// This method handles recognition of channel
|
// This method handles recognition of channel
|
||||||
// (to know if the message is destinated to the Arduino)
|
// (to know if the message is destinated to the Arduino)
|
||||||
|
|
@ -827,8 +811,8 @@ inline bool MidiInterface<SerialPort>::inputFilter(Channel inChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private method: reset input attributes
|
// Private method: reset input attributes
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
inline void MidiInterface<SerialPort>::resetInput()
|
inline void MidiInterface<SerialPort, Settings>::resetInput()
|
||||||
{
|
{
|
||||||
mPendingMessageIndex = 0;
|
mPendingMessageIndex = 0;
|
||||||
mPendingMessageExpectedLenght = 0;
|
mPendingMessageExpectedLenght = 0;
|
||||||
|
|
@ -841,8 +825,8 @@ inline void MidiInterface<SerialPort>::resetInput()
|
||||||
|
|
||||||
Returns an enumerated type. @see MidiType
|
Returns an enumerated type. @see MidiType
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
MidiType MidiInterface<SerialPort>::getType() const
|
inline MidiType MidiInterface<SerialPort, Settings>::getType() const
|
||||||
{
|
{
|
||||||
return mMessage.type;
|
return mMessage.type;
|
||||||
}
|
}
|
||||||
|
|
@ -852,22 +836,22 @@ MidiType MidiInterface<SerialPort>::getType() const
|
||||||
\return Channel range is 1 to 16.
|
\return Channel range is 1 to 16.
|
||||||
For non-channel messages, this will return 0.
|
For non-channel messages, this will return 0.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
Channel MidiInterface<SerialPort>::getChannel() const
|
inline Channel MidiInterface<SerialPort, Settings>::getChannel() const
|
||||||
{
|
{
|
||||||
return mMessage.channel;
|
return mMessage.channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Get the first data byte of the last received message. */
|
/*! \brief Get the first data byte of the last received message. */
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
DataByte MidiInterface<SerialPort>::getData1() const
|
inline DataByte MidiInterface<SerialPort, Settings>::getData1() const
|
||||||
{
|
{
|
||||||
return mMessage.data1;
|
return mMessage.data1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Get the second data byte of the last received message. */
|
/*! \brief Get the second data byte of the last received message. */
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
DataByte MidiInterface<SerialPort>::getData2() const
|
inline DataByte MidiInterface<SerialPort, Settings>::getData2() const
|
||||||
{
|
{
|
||||||
return mMessage.data2;
|
return mMessage.data2;
|
||||||
}
|
}
|
||||||
|
|
@ -876,8 +860,8 @@ DataByte MidiInterface<SerialPort>::getData2() const
|
||||||
|
|
||||||
@see getSysExArrayLength to get the array's length in bytes.
|
@see getSysExArrayLength to get the array's length in bytes.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
const byte* MidiInterface<SerialPort>::getSysExArray() const
|
inline const byte* MidiInterface<SerialPort, Settings>::getSysExArray() const
|
||||||
{
|
{
|
||||||
return mMessage.sysexArray;
|
return mMessage.sysexArray;
|
||||||
}
|
}
|
||||||
|
|
@ -887,24 +871,23 @@ const byte* MidiInterface<SerialPort>::getSysExArray() const
|
||||||
It is coded using data1 as LSB and data2 as MSB.
|
It is coded using data1 as LSB and data2 as MSB.
|
||||||
\return The array's length, in bytes.
|
\return The array's length, in bytes.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
unsigned MidiInterface<SerialPort>::getSysExArrayLength() const
|
inline unsigned MidiInterface<SerialPort, Settings>::getSysExArrayLength() const
|
||||||
{
|
{
|
||||||
const unsigned size = ((unsigned)(mMessage.data2) << 8) | mMessage.data1;
|
return mMessage.getSysExSize();
|
||||||
return (size > MIDI_SYSEX_ARRAY_SIZE) ? MIDI_SYSEX_ARRAY_SIZE : size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Check if a valid message is stored in the structure. */
|
/*! \brief Check if a valid message is stored in the structure. */
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
bool MidiInterface<SerialPort>::check() const
|
inline bool MidiInterface<SerialPort, Settings>::check() const
|
||||||
{
|
{
|
||||||
return mMessage.valid;
|
return mMessage.valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
Channel MidiInterface<SerialPort>::getInputChannel() const
|
inline Channel MidiInterface<SerialPort, Settings>::getInputChannel() const
|
||||||
{
|
{
|
||||||
return mInputChannel;
|
return mInputChannel;
|
||||||
}
|
}
|
||||||
|
|
@ -913,8 +896,8 @@ Channel MidiInterface<SerialPort>::getInputChannel() const
|
||||||
\param inChannel the channel value. Valid values are 1 to 16, MIDI_CHANNEL_OMNI
|
\param inChannel the channel value. Valid values are 1 to 16, MIDI_CHANNEL_OMNI
|
||||||
if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input.
|
if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::setInputChannel(Channel inChannel)
|
inline void MidiInterface<SerialPort, Settings>::setInputChannel(Channel inChannel)
|
||||||
{
|
{
|
||||||
mInputChannel = inChannel;
|
mInputChannel = inChannel;
|
||||||
}
|
}
|
||||||
|
|
@ -926,8 +909,8 @@ void MidiInterface<SerialPort>::setInputChannel(Channel inChannel)
|
||||||
This is a utility static method, used internally,
|
This is a utility static method, used internally,
|
||||||
made public so you can handle MidiTypes more easily.
|
made public so you can handle MidiTypes more easily.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(byte inStatus)
|
MidiType MidiInterface<SerialPort, Settings>::getTypeFromStatusByte(byte inStatus)
|
||||||
{
|
{
|
||||||
if ((inStatus < 0x80) ||
|
if ((inStatus < 0x80) ||
|
||||||
(inStatus == 0xf4) ||
|
(inStatus == 0xf4) ||
|
||||||
|
|
@ -941,22 +924,22 @@ MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(byte inStatus)
|
||||||
if (inStatus < 0xf0)
|
if (inStatus < 0xf0)
|
||||||
{
|
{
|
||||||
// Channel message, remove channel nibble.
|
// Channel message, remove channel nibble.
|
||||||
return (MidiType)(inStatus & 0xf0);
|
return MidiType(inStatus & 0xf0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (MidiType)inStatus;
|
return MidiType(inStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Returns channel in the range 1-16
|
/*! \brief Returns channel in the range 1-16
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
inline Channel MidiInterface<SerialPort>::getChannelFromStatusByte(byte inStatus)
|
inline Channel MidiInterface<SerialPort, Settings>::getChannelFromStatusByte(byte inStatus)
|
||||||
{
|
{
|
||||||
return (inStatus & 0x0f) + 1;
|
return (inStatus & 0x0f) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
bool MidiInterface<SerialPort>::isChannelMessage(MidiType inType)
|
bool MidiInterface<SerialPort, Settings>::isChannelMessage(MidiType inType)
|
||||||
{
|
{
|
||||||
return (inType == NoteOff ||
|
return (inType == NoteOff ||
|
||||||
inType == NoteOn ||
|
inType == NoteOn ||
|
||||||
|
|
@ -969,30 +952,28 @@ bool MidiInterface<SerialPort>::isChannelMessage(MidiType inType)
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if MIDI_USE_CALLBACKS
|
|
||||||
|
|
||||||
/*! \addtogroup callbacks
|
/*! \addtogroup callbacks
|
||||||
@{
|
@{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSystemExclusive(void (*fptr)(byte* array, byte size)) { mSystemExclusiveCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSystemExclusive(void (*fptr)(byte* array, unsigned size)) { mSystemExclusiveCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSongPosition(void (*fptr)(unsigned beats)) { mSongPositionCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSongPosition(void (*fptr)(unsigned beats)) { mSongPositionCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; }
|
||||||
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; }
|
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; }
|
||||||
|
|
||||||
/*! \brief Detach an external function from the given type.
|
/*! \brief Detach an external function from the given type.
|
||||||
|
|
||||||
|
|
@ -1000,8 +981,8 @@ template<class SerialPort> void MidiInterface<SerialPort>::setHandleSystemReset(
|
||||||
\param inType The type of message to unbind.
|
\param inType The type of message to unbind.
|
||||||
When a message of this type is received, no function will be called.
|
When a message of this type is received, no function will be called.
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::disconnectCallbackFromType(MidiType inType)
|
void MidiInterface<SerialPort, Settings>::disconnectCallbackFromType(MidiType inType)
|
||||||
{
|
{
|
||||||
switch (inType)
|
switch (inType)
|
||||||
{
|
{
|
||||||
|
|
@ -1031,8 +1012,8 @@ void MidiInterface<SerialPort>::disconnectCallbackFromType(MidiType inType)
|
||||||
/*! @} */ // End of doc group MIDI Callbacks
|
/*! @} */ // End of doc group MIDI Callbacks
|
||||||
|
|
||||||
// Private - launch callback function based on received type.
|
// Private - launch callback function based on received type.
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::launchCallback()
|
void MidiInterface<SerialPort, Settings>::launchCallback()
|
||||||
{
|
{
|
||||||
// The order is mixed to allow frequent messages to trigger their callback faster.
|
// The order is mixed to allow frequent messages to trigger their callback faster.
|
||||||
switch (mMessage.type)
|
switch (mMessage.type)
|
||||||
|
|
@ -1055,7 +1036,7 @@ void MidiInterface<SerialPort>::launchCallback()
|
||||||
case AfterTouchChannel: if (mAfterTouchChannelCallback != 0) mAfterTouchChannelCallback(mMessage.channel, mMessage.data1); break;
|
case AfterTouchChannel: if (mAfterTouchChannelCallback != 0) mAfterTouchChannelCallback(mMessage.channel, mMessage.data1); break;
|
||||||
|
|
||||||
case ProgramChange: if (mProgramChangeCallback != 0) mProgramChangeCallback(mMessage.channel, mMessage.data1); break;
|
case ProgramChange: if (mProgramChangeCallback != 0) mProgramChangeCallback(mMessage.channel, mMessage.data1); break;
|
||||||
case SystemExclusive: if (mSystemExclusiveCallback != 0) mSystemExclusiveCallback(mMessage.sysexArray, mMessage.data1); break;
|
case SystemExclusive: if (mSystemExclusiveCallback != 0) mSystemExclusiveCallback(mMessage.sysexArray, mMessage.getSysExSize()); break;
|
||||||
|
|
||||||
// Occasional messages
|
// Occasional messages
|
||||||
case TimeCodeQuarterFrame: if (mTimeCodeQuarterFrameCallback != 0) mTimeCodeQuarterFrameCallback(mMessage.data1); break;
|
case TimeCodeQuarterFrame: if (mTimeCodeQuarterFrameCallback != 0) mTimeCodeQuarterFrameCallback(mMessage.data1); break;
|
||||||
|
|
@ -1070,19 +1051,12 @@ void MidiInterface<SerialPort>::launchCallback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MIDI_USE_CALLBACKS
|
|
||||||
|
|
||||||
/*! @} */ // End of doc group MIDI Input
|
/*! @} */ // End of doc group MIDI Input
|
||||||
|
|
||||||
#endif // MIDI_BUILD_INPUT
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Thru
|
// Thru
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU)
|
|
||||||
|
|
||||||
/*! \addtogroup thru
|
/*! \addtogroup thru
|
||||||
@{
|
@{
|
||||||
*/
|
*/
|
||||||
|
|
@ -1092,8 +1066,8 @@ void MidiInterface<SerialPort>::launchCallback()
|
||||||
|
|
||||||
@see MidiFilterMode
|
@see MidiFilterMode
|
||||||
*/
|
*/
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::setThruFilterMode(MidiFilterMode inThruFilterMode)
|
void MidiInterface<SerialPort, Settings>::setThruFilterMode(MidiFilterMode inThruFilterMode)
|
||||||
{
|
{
|
||||||
mThruFilterMode = inThruFilterMode;
|
mThruFilterMode = inThruFilterMode;
|
||||||
if (mThruFilterMode != Off)
|
if (mThruFilterMode != Off)
|
||||||
|
|
@ -1102,27 +1076,27 @@ void MidiInterface<SerialPort>::setThruFilterMode(MidiFilterMode inThruFilterMod
|
||||||
mThruActivated = false;
|
mThruActivated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
MidiFilterMode MidiInterface<SerialPort>::getFilterMode() const
|
MidiFilterMode MidiInterface<SerialPort, Settings>::getFilterMode() const
|
||||||
{
|
{
|
||||||
return mThruFilterMode;
|
return mThruFilterMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
bool MidiInterface<SerialPort>::getThruState() const
|
bool MidiInterface<SerialPort, Settings>::getThruState() const
|
||||||
{
|
{
|
||||||
return mThruActivated;
|
return mThruActivated;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::turnThruOn(MidiFilterMode inThruFilterMode)
|
void MidiInterface<SerialPort, Settings>::turnThruOn(MidiFilterMode inThruFilterMode)
|
||||||
{
|
{
|
||||||
mThruActivated = true;
|
mThruActivated = true;
|
||||||
mThruFilterMode = inThruFilterMode;
|
mThruFilterMode = inThruFilterMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::turnThruOff()
|
void MidiInterface<SerialPort, Settings>::turnThruOff()
|
||||||
{
|
{
|
||||||
mThruActivated = false;
|
mThruActivated = false;
|
||||||
mThruFilterMode = Off;
|
mThruFilterMode = Off;
|
||||||
|
|
@ -1136,8 +1110,8 @@ void MidiInterface<SerialPort>::turnThruOff()
|
||||||
// to output unless filter is set to Off.
|
// to output unless filter is set to Off.
|
||||||
// - Channel messages are passed to the output whether their channel
|
// - Channel messages are passed to the output whether their channel
|
||||||
// is matching the input channel and the filter setting
|
// is matching the input channel and the filter setting
|
||||||
template<class SerialPort>
|
template<class SerialPort, class Settings>
|
||||||
void MidiInterface<SerialPort>::thruFilter(Channel inChannel)
|
void MidiInterface<SerialPort, Settings>::thruFilter(Channel inChannel)
|
||||||
{
|
{
|
||||||
// If the feature is disabled, don't do anything.
|
// If the feature is disabled, don't do anything.
|
||||||
if (!mThruActivated || (mThruFilterMode == Off))
|
if (!mThruActivated || (mThruFilterMode == Off))
|
||||||
|
|
@ -1227,8 +1201,4 @@ void MidiInterface<SerialPort>::thruFilter(Channel inChannel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MIDI_BUILD_THRU
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
END_MIDI_NAMESPACE
|
END_MIDI_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* @file midi_Defs.h
|
* @file midi_Defs.h
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino - Definitions
|
* @brief MIDI Library for the Arduino - Definitions
|
||||||
* @version 4.1
|
* @version 4.2
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
|
@ -24,7 +24,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "midi_Namespace.h"
|
#include "midi_Namespace.h"
|
||||||
|
|
||||||
|
#if ARDUINO
|
||||||
|
#include <Arduino.h>
|
||||||
|
#else
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
typedef uint8_t byte;
|
||||||
|
#endif
|
||||||
|
|
||||||
BEGIN_MIDI_NAMESPACE
|
BEGIN_MIDI_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -39,8 +45,6 @@ BEGIN_MIDI_NAMESPACE
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Type definitions
|
// Type definitions
|
||||||
|
|
||||||
typedef uint8_t byte;
|
|
||||||
|
|
||||||
typedef byte StatusByte;
|
typedef byte StatusByte;
|
||||||
typedef byte DataByte;
|
typedef byte DataByte;
|
||||||
typedef byte Channel;
|
typedef byte Channel;
|
||||||
|
|
@ -155,63 +159,35 @@ enum MidiControlChangeNumber
|
||||||
PolyModeOn = 127
|
PolyModeOn = 127
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/*! The midimsg structure contains decoded data of a MIDI message
|
|
||||||
read from the serial port with read()
|
|
||||||
*/
|
|
||||||
struct Message
|
|
||||||
{
|
|
||||||
|
|
||||||
/*! The MIDI channel on which the message was recieved.
|
|
||||||
\n Value goes from 1 to 16.
|
|
||||||
*/
|
|
||||||
Channel channel;
|
|
||||||
|
|
||||||
/*! The type of the message
|
|
||||||
(see the MidiType enum for types reference)
|
|
||||||
*/
|
|
||||||
MidiType type;
|
|
||||||
|
|
||||||
/*! The first data byte.
|
|
||||||
\n Value goes from 0 to 127.
|
|
||||||
*/
|
|
||||||
DataByte data1;
|
|
||||||
|
|
||||||
/*! The second data byte.
|
|
||||||
If the message is only 2 bytes long, this one is null.
|
|
||||||
\n Value goes from 0 to 127.
|
|
||||||
*/
|
|
||||||
DataByte data2;
|
|
||||||
|
|
||||||
/*! System Exclusive dedicated byte array.
|
|
||||||
\n Array length is stocked on 16 bits,
|
|
||||||
in data1 (LSB) and data2 (MSB)
|
|
||||||
*/
|
|
||||||
DataByte sysexArray[MIDI_SYSEX_ARRAY_SIZE];
|
|
||||||
|
|
||||||
/*! This boolean indicates if the message is valid or not.
|
|
||||||
There is no channel consideration here,
|
|
||||||
validity means the message respects the MIDI norm.
|
|
||||||
*/
|
|
||||||
bool valid;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*! \brief Create an instance of the library attached to a serial port.
|
/*! \brief Create an instance of the library attached to a serial port.
|
||||||
You can use HardwareSerial or SoftwareSerial for the serial port.
|
You can use HardwareSerial or SoftwareSerial for the serial port.
|
||||||
|
Example: MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, midi2);
|
||||||
|
Then call midi2.begin(), midi2.read() etc..
|
||||||
*/
|
*/
|
||||||
#define MIDI_CREATE_INSTANCE(Type, SerialPort, Name) \
|
#define MIDI_CREATE_INSTANCE(Type, SerialPort, Name) \
|
||||||
midi::MidiInterface<Type> Name((Type&)SerialPort);
|
midi::MidiInterface<Type> Name((Type&)SerialPort);
|
||||||
|
|
||||||
/*! \brief Shortcut for MIDI Interface class with template argument.
|
#if defined(ARDUINO_SAM_DUE) || defined(USBCON)
|
||||||
The class name for a MIDI object using the hardware UART would be
|
// Leonardo, Due and other USB boards use Serial1 by default.
|
||||||
midi::MidiInterface<HardwareSerial>, when the macro is MIDI_CLASS(HardwareSerial).
|
#define MIDI_CREATE_DEFAULT_INSTANCE() \
|
||||||
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
|
||||||
|
#else
|
||||||
|
/*! \brief Create an instance of the library with default name, serial port
|
||||||
|
and settings, for compatibility with sketches written with pre-v4.2 MIDI Lib,
|
||||||
|
or if you don't bother using custom names, serial port or settings.
|
||||||
*/
|
*/
|
||||||
#define MIDI_CLASS(Type) \
|
#define MIDI_CREATE_DEFAULT_INSTANCE() \
|
||||||
midi::MidiInterface<Type>
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, MIDI);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! \brief Create an instance of the library attached to a serial port with
|
||||||
|
custom settings.
|
||||||
|
@see DefaultSettings
|
||||||
|
@see MIDI_CREATE_INSTANCE
|
||||||
|
*/
|
||||||
|
#define MIDI_CREATE_CUSTOM_INSTANCE(Type, SerialPort, Name, Settings) \
|
||||||
|
midi::MidiInterface<Type, Settings> Name((Type&)SerialPort);
|
||||||
|
|
||||||
END_MIDI_NAMESPACE
|
END_MIDI_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*!
|
||||||
|
* @file midi_Message.h
|
||||||
|
* Project Arduino MIDI Library
|
||||||
|
* @brief MIDI Library for the Arduino - Message struct definition
|
||||||
|
* @version 4.2
|
||||||
|
* @author Francois Best
|
||||||
|
* @date 11/06/14
|
||||||
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "midi_Namespace.h"
|
||||||
|
#include "midi_Defs.h"
|
||||||
|
|
||||||
|
BEGIN_MIDI_NAMESPACE
|
||||||
|
|
||||||
|
/*! The Message structure contains decoded data of a MIDI message
|
||||||
|
read from the serial port with read()
|
||||||
|
*/
|
||||||
|
template<unsigned SysExMaxSize>
|
||||||
|
struct Message
|
||||||
|
{
|
||||||
|
/*! The maximum size for the System Exclusive array.
|
||||||
|
*/
|
||||||
|
static const unsigned sSysExMaxSize = SysExMaxSize;
|
||||||
|
|
||||||
|
/*! The MIDI channel on which the message was recieved.
|
||||||
|
\n Value goes from 1 to 16.
|
||||||
|
*/
|
||||||
|
Channel channel;
|
||||||
|
|
||||||
|
/*! The type of the message
|
||||||
|
(see the MidiType enum for types reference)
|
||||||
|
*/
|
||||||
|
MidiType type;
|
||||||
|
|
||||||
|
/*! The first data byte.
|
||||||
|
\n Value goes from 0 to 127.
|
||||||
|
*/
|
||||||
|
DataByte data1;
|
||||||
|
|
||||||
|
/*! The second data byte.
|
||||||
|
If the message is only 2 bytes long, this one is null.
|
||||||
|
\n Value goes from 0 to 127.
|
||||||
|
*/
|
||||||
|
DataByte data2;
|
||||||
|
|
||||||
|
/*! System Exclusive dedicated byte array.
|
||||||
|
\n Array length is stocked on 16 bits,
|
||||||
|
in data1 (LSB) and data2 (MSB)
|
||||||
|
*/
|
||||||
|
DataByte sysexArray[sSysExMaxSize];
|
||||||
|
|
||||||
|
/*! This boolean indicates if the message is valid or not.
|
||||||
|
There is no channel consideration here,
|
||||||
|
validity means the message respects the MIDI norm.
|
||||||
|
*/
|
||||||
|
bool valid;
|
||||||
|
|
||||||
|
inline unsigned getSysExSize() const
|
||||||
|
{
|
||||||
|
const unsigned size = unsigned(data2) << 8 | data1;
|
||||||
|
return size > sSysExMaxSize ? sSysExMaxSize : size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
END_MIDI_NAMESPACE
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* @file midi_Namespace.h
|
* @file midi_Namespace.h
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino - Namespace declaration
|
* @brief MIDI Library for the Arduino - Namespace declaration
|
||||||
* @version 4.1
|
* @version 4.2
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* @file midi_Settings.h
|
* @file midi_Settings.h
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino - Settings
|
* @brief MIDI Library for the Arduino - Settings
|
||||||
* @version 4.1
|
* @version 4.2
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
|
@ -23,80 +23,54 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "midi_Namespace.h"
|
#include "midi_Defs.h"
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Here are a few settings you can change to customize
|
|
||||||
// the library for your own project. You can for example
|
|
||||||
// choose to compile only parts of it so you gain flash
|
|
||||||
// space and optimise the speed of your sketch.
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Compilation flags. Set them to 1 to build the associated feature
|
|
||||||
// (MIDI in, out, thru), or to 0 to disable the feature and save space.
|
|
||||||
// Note that thru can work only if input and output are enabled.
|
|
||||||
|
|
||||||
#define MIDI_BUILD_INPUT 1
|
|
||||||
#define MIDI_BUILD_OUTPUT 1
|
|
||||||
#define MIDI_BUILD_THRU 1
|
|
||||||
|
|
||||||
#define MIDI_USE_CALLBACKS 1
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Create a MIDI object automatically on the port defined with MIDI_SERIAL_PORT.
|
|
||||||
#ifndef MIDI_AUTO_INSTANCIATE
|
|
||||||
# ifdef ARDUINO
|
|
||||||
# define MIDI_AUTO_INSTANCIATE 1
|
|
||||||
# else
|
|
||||||
# define MIDI_AUTO_INSTANCIATE 0 ///< @see MIDI_CREATE_INSTANCE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
// Default serial port configuration (if MIDI_AUTO_INSTANCIATE is set)
|
|
||||||
|
|
||||||
// Set the default port to use for MIDI.
|
|
||||||
#if MIDI_AUTO_INSTANCIATE
|
|
||||||
# ifdef ARDUINO
|
|
||||||
# include "Arduino.h"
|
|
||||||
# ifdef USBCON
|
|
||||||
# define MIDI_DEFAULT_SERIAL_PORT Serial1 // For Leonardo
|
|
||||||
# else
|
|
||||||
# define MIDI_DEFAULT_SERIAL_PORT Serial // For other Arduinos
|
|
||||||
# endif
|
|
||||||
# define MIDI_DEFAULT_SERIAL_CLASS HardwareSerial
|
|
||||||
# include "HardwareSerial.h"
|
|
||||||
# else
|
|
||||||
# error Auto-instanciation disabled. Use MIDI_CREATE_INSTANCE macro.
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
// Misc. options
|
|
||||||
|
|
||||||
// Running status enables short messages when sending multiple values
|
|
||||||
// of the same type and channel.
|
|
||||||
// Set to 0 if you have troubles controlling your hardware.
|
|
||||||
#define MIDI_USE_RUNNING_STATUS 1
|
|
||||||
|
|
||||||
// NoteOn with 0 velocity should be handled as NoteOf.
|
|
||||||
// Set to 1 to get NoteOff events when receiving null-velocity NoteOn messages.
|
|
||||||
// Set to 0 to get NoteOn events when receiving null-velocity NoteOn messages.
|
|
||||||
#define MIDI_HANDLE_NULL_VELOCITY_NOTE_ON_AS_NOTE_OFF 1
|
|
||||||
|
|
||||||
// Setting this to 1 will make MIDI.read parse only one byte of data for each
|
|
||||||
// call when data is available. This can speed up your application if receiving
|
|
||||||
// a lot of traffic, but might induce MIDI Thru and treatment latency.
|
|
||||||
#define MIDI_USE_1BYTE_PARSING 1
|
|
||||||
|
|
||||||
#define MIDI_BAUDRATE 31250
|
|
||||||
#define MIDI_SYSEX_ARRAY_SIZE 255 // Maximum size is 65535 bytes.
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
BEGIN_MIDI_NAMESPACE
|
BEGIN_MIDI_NAMESPACE
|
||||||
|
|
||||||
|
/*! \brief Default Settings for the MIDI Library.
|
||||||
|
|
||||||
|
To change the default settings, don't edit them there, create a subclass and
|
||||||
|
override the values in that subclass, then use the MIDI_CREATE_CUSTOM_INSTANCE
|
||||||
|
macro to create your instance. The settings you don't override will keep their
|
||||||
|
default value. Eg:
|
||||||
|
\code{.cpp}
|
||||||
|
struct MySettings : public midi::DefaultSettings
|
||||||
|
{
|
||||||
|
static const bool UseRunningStatus = false; // Messes with my old equipment!
|
||||||
|
};
|
||||||
|
|
||||||
|
MIDI_CREATE_CUSTOM_INSTANCE(HardwareSerial, Serial2, midi, MySettings);
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
struct DefaultSettings
|
||||||
|
{
|
||||||
|
/*! Running status enables short messages when sending multiple values
|
||||||
|
of the same type and channel.\n
|
||||||
|
Set to 0 if you have troubles controlling your hardware.
|
||||||
|
*/
|
||||||
|
static const bool UseRunningStatus = true;
|
||||||
|
|
||||||
|
/* NoteOn with 0 velocity should be handled as NoteOf.\n
|
||||||
|
Set to 1 to get NoteOff events when receiving null-velocity NoteOn messages.\n
|
||||||
|
Set to 0 to get NoteOn events when receiving null-velocity NoteOn messages.
|
||||||
|
*/
|
||||||
|
static const bool HandleNullVelocityNoteOnAsNoteOff = true;
|
||||||
|
|
||||||
|
// Setting this to 1 will make MIDI.read parse only one byte of data for each
|
||||||
|
// call when data is available. This can speed up your application if receiving
|
||||||
|
// a lot of traffic, but might induce MIDI Thru and treatment latency.
|
||||||
|
static const bool Use1ByteParsing = true;
|
||||||
|
|
||||||
|
/*! Override the default MIDI baudrate to transmit over USB serial, to
|
||||||
|
a decoding program such as Hairless MIDI (set baudrate to 115200)\n
|
||||||
|
http://projectgus.github.io/hairless-midiserial/
|
||||||
|
*/
|
||||||
|
static const long BaudRate = 31250;
|
||||||
|
|
||||||
|
/*! Maximum size of SysEx receivable. Decrease to save RAM if you don't expect
|
||||||
|
to receive SysEx, or adjust accordingly.
|
||||||
|
*/
|
||||||
|
static const unsigned SysExMaxSize = 128;
|
||||||
|
};
|
||||||
|
|
||||||
END_MIDI_NAMESPACE
|
END_MIDI_NAMESPACE
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue