Fix SysEx size callback bug, using template settings instead of preprocessor macros.
This commit is contained in:
parent
1ff874c70d
commit
219340ea96
|
|
@ -4,6 +4,8 @@
|
|||
// Here, when receiving any message on channel 4, the Arduino
|
||||
// will blink a led and play back a note for 1 second.
|
||||
|
||||
MIDI_CREATE_DEFAULT_INSTANCE();
|
||||
|
||||
#define LED 13 // LED pin on Arduino Uno
|
||||
|
||||
void setup()
|
||||
|
|
|
|||
|
|
@ -1,33 +1,39 @@
|
|||
#include <MIDI.h>
|
||||
|
||||
MIDI_CREATE_DEFAULT_INSTANCE();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// This function will be automatically called when a NoteOn is received.
|
||||
// It must be a void-returning function with the correct parameters,
|
||||
// see documentation here:
|
||||
// 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.
|
||||
|
||||
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
|
||||
}
|
||||
// Do whatever you want when a note is pressed.
|
||||
|
||||
// Try to keep your callbacks short (no delays ect)
|
||||
// otherwise it would slow down the loop() and have a bad impact
|
||||
// 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()
|
||||
{
|
||||
// Connect the HandleNoteOn function to the library,
|
||||
// Connect the handleNoteOn function to the library,
|
||||
// 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
|
||||
MIDI.begin(MIDI_CHANNEL_OMNI);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
#include <MIDI.h>
|
||||
|
||||
MIDI_CREATE_DEFAULT_INSTANCE();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// This example shows the old way of checking for input messages.
|
||||
// It's simpler to use the callbacks now, check out the dedicated example.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#include "noteList.h"
|
||||
#include "pitches.h"
|
||||
|
||||
MIDI_CREATE_DEFAULT_INSTANCE();
|
||||
|
||||
#ifdef ARDUINO_SAM_DUE // Due has no tone function (yet), overriden to prevent build errors.
|
||||
#define tone(...)
|
||||
#define noTone(...)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import sys
|
|||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import argparse
|
||||
from pprint import pprint
|
||||
from midi import *
|
||||
from tester import *
|
||||
|
|
@ -138,28 +139,42 @@ class ArduinoMidiLibrary:
|
|||
# ------------------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
midiInterface = MidiInterface()
|
||||
tester = Tester(midiInterface)
|
||||
midiInterface.listenerCallback = tester.handleMidiInput
|
||||
|
||||
tester.checkThru([Midi.NoteOn, 64, 80])
|
||||
tester.checkThru([Midi.AfterTouchChannel, 1])
|
||||
tester.checkThru([2])
|
||||
tester.checkThru([3])
|
||||
tester.checkThru([Midi.NoteOn, 64, 0])
|
||||
tester.checkThru([65, 127])
|
||||
tester.checkThru([65, 0])
|
||||
tester.checkThru([66, 127])
|
||||
tester.checkThru([66, 0])
|
||||
info = "Validator script for the Arduino MIDI Library."
|
||||
arg_parser = argparse.ArgumentParser(description = info)
|
||||
|
||||
#lib = ArduinoMidiLibrary()
|
||||
#lib.install()
|
||||
#if lib.validate():
|
||||
# print('Validation passed')
|
||||
#else:
|
||||
# print('Validation failed')
|
||||
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()
|
||||
tester = Tester(midiInterface)
|
||||
midiInterface.listenerCallback = tester.handleMidiInput
|
||||
|
||||
tester.checkThru([Midi.NoteOn, 64, 80])
|
||||
tester.checkThru([Midi.AfterTouchChannel, 1])
|
||||
tester.checkThru([2])
|
||||
tester.checkThru([3])
|
||||
tester.checkThru([Midi.NoteOn, 64, 0])
|
||||
tester.checkThru([65, 127])
|
||||
tester.checkThru([65, 0])
|
||||
tester.checkThru([66, 127])
|
||||
tester.checkThru([66, 0])
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
20
src/MIDI.h
20
src/MIDI.h
|
|
@ -23,8 +23,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "midi_Settings.h"
|
||||
#include "midi_Defs.h"
|
||||
#include "midi_Settings.h"
|
||||
#include "midi_Message.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -131,7 +132,7 @@ public:
|
|||
inline void setHandleProgramChange(void (*fptr)(byte channel, byte number));
|
||||
inline void setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure));
|
||||
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 setHandleSongPosition(void (*fptr)(unsigned beats));
|
||||
inline void setHandleSongSelect(void (*fptr)(byte songnumber));
|
||||
|
|
@ -155,7 +156,7 @@ private:
|
|||
void (*mProgramChangeCallback)(byte channel, byte);
|
||||
void (*mAfterTouchChannelCallback)(byte channel, byte);
|
||||
void (*mPitchBendCallback)(byte channel, int);
|
||||
void (*mSystemExclusiveCallback)(byte * array, byte size);
|
||||
void (*mSystemExclusiveCallback)(byte * array, unsigned size);
|
||||
void (*mTimeCodeQuarterFrameCallback)(byte data);
|
||||
void (*mSongPositionCallback)(unsigned beats);
|
||||
void (*mSongSelectCallback)(byte songnumber);
|
||||
|
|
@ -192,25 +193,22 @@ private:
|
|||
bool mThruActivated : 1;
|
||||
MidiFilterMode mThruFilterMode : 7;
|
||||
|
||||
private:
|
||||
typedef Message<Settings::SysExMaxSize> MidiMessage;
|
||||
|
||||
private:
|
||||
StatusByte mRunningStatus_RX;
|
||||
StatusByte mRunningStatus_TX;
|
||||
Channel mInputChannel;
|
||||
byte mPendingMessage[3];
|
||||
unsigned mPendingMessageExpectedLenght;
|
||||
unsigned mPendingMessageIndex;
|
||||
Message mMessage;
|
||||
MidiMessage mMessage;
|
||||
|
||||
private:
|
||||
inline StatusByte getStatus(MidiType inType,
|
||||
Channel inChannel) const;
|
||||
|
||||
|
||||
|
||||
#if MIDI_USE_RUNNING_STATUS
|
||||
private:
|
||||
StatusByte mRunningStatus_TX;
|
||||
#endif
|
||||
|
||||
private:
|
||||
SerialPort& mSerial;
|
||||
};
|
||||
|
|
|
|||
77
src/MIDI.hpp
77
src/MIDI.hpp
|
|
@ -79,18 +79,10 @@ void MidiInterface<SerialPort, Settings>::begin(Channel inChannel)
|
|||
mSerial.begin(Settings::BaudRate);
|
||||
#endif
|
||||
|
||||
#if MIDI_BUILD_OUTPUT
|
||||
if (Settings::UseRunningStatus)
|
||||
{
|
||||
mRunningStatus_TX = InvalidType;
|
||||
}
|
||||
#endif // MIDI_BUILD_OUTPUT
|
||||
|
||||
|
||||
#if MIDI_BUILD_INPUT
|
||||
|
||||
mInputChannel = inChannel;
|
||||
mRunningStatus_TX = InvalidType;
|
||||
mRunningStatus_RX = InvalidType;
|
||||
|
||||
mPendingMessageIndex = 0;
|
||||
mPendingMessageExpectedLenght = 0;
|
||||
|
||||
|
|
@ -100,25 +92,14 @@ void MidiInterface<SerialPort, Settings>::begin(Channel inChannel)
|
|||
mMessage.data1 = 0;
|
||||
mMessage.data2 = 0;
|
||||
|
||||
#endif // MIDI_BUILD_INPUT
|
||||
|
||||
|
||||
#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU) // Thru
|
||||
|
||||
mThruFilterMode = Full;
|
||||
mThruActivated = true;
|
||||
|
||||
#endif // Thru
|
||||
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Output
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#if MIDI_BUILD_OUTPUT
|
||||
|
||||
/*! \addtogroup output
|
||||
@{
|
||||
*/
|
||||
|
|
@ -459,15 +440,10 @@ StatusByte MidiInterface<SerialPort, Settings>::getStatus(MidiType inType,
|
|||
return ((byte)inType | ((inChannel - 1) & 0x0f));
|
||||
}
|
||||
|
||||
#endif // MIDI_BUILD_OUTPUT
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Input
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#if MIDI_BUILD_INPUT
|
||||
|
||||
/*! \addtogroup input
|
||||
@{
|
||||
*/
|
||||
|
|
@ -505,9 +481,7 @@ inline bool MidiInterface<SerialPort, Settings>::read(Channel inChannel)
|
|||
launchCallback();
|
||||
}
|
||||
|
||||
#if MIDI_BUILD_THRU
|
||||
thruFilter(inChannel);
|
||||
#endif
|
||||
|
||||
return channelMatch;
|
||||
}
|
||||
|
|
@ -604,8 +578,8 @@ bool MidiInterface<SerialPort, Settings>::parse()
|
|||
|
||||
case SystemExclusive:
|
||||
// The message can be any lenght
|
||||
// between 3 and MIDI_SYSEX_ARRAY_SIZE bytes
|
||||
mPendingMessageExpectedLenght = MIDI_SYSEX_ARRAY_SIZE;
|
||||
// between 3 and MidiMessage::sSysExMaxSize bytes
|
||||
mPendingMessageExpectedLenght = MidiMessage::sSysExMaxSize;
|
||||
mRunningStatus_RX = InvalidType;
|
||||
mMessage.sysexArray[0] = SystemExclusive;
|
||||
break;
|
||||
|
|
@ -693,8 +667,8 @@ bool MidiInterface<SerialPort, Settings>::parse()
|
|||
mMessage.type = SystemExclusive;
|
||||
|
||||
// Get length
|
||||
mMessage.data1 = mPendingMessageIndex & 0xff;
|
||||
mMessage.data2 = mPendingMessageIndex >> 8;
|
||||
mMessage.data1 = mPendingMessageIndex & 0xff; // LSB
|
||||
mMessage.data2 = mPendingMessageIndex >> 8; // MSB
|
||||
mMessage.channel = 0;
|
||||
mMessage.valid = true;
|
||||
|
||||
|
|
@ -725,7 +699,7 @@ bool MidiInterface<SerialPort, Settings>::parse()
|
|||
{
|
||||
// "FML" case: fall down here with an overflown SysEx..
|
||||
// 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)
|
||||
{
|
||||
resetInput();
|
||||
|
|
@ -852,7 +826,7 @@ inline void MidiInterface<SerialPort, Settings>::resetInput()
|
|||
Returns an enumerated type. @see MidiType
|
||||
*/
|
||||
template<class SerialPort, class Settings>
|
||||
MidiType MidiInterface<SerialPort, Settings>::getType() const
|
||||
inline MidiType MidiInterface<SerialPort, Settings>::getType() const
|
||||
{
|
||||
return mMessage.type;
|
||||
}
|
||||
|
|
@ -863,21 +837,21 @@ MidiType MidiInterface<SerialPort, Settings>::getType() const
|
|||
For non-channel messages, this will return 0.
|
||||
*/
|
||||
template<class SerialPort, class Settings>
|
||||
Channel MidiInterface<SerialPort, Settings>::getChannel() const
|
||||
inline Channel MidiInterface<SerialPort, Settings>::getChannel() const
|
||||
{
|
||||
return mMessage.channel;
|
||||
}
|
||||
|
||||
/*! \brief Get the first data byte of the last received message. */
|
||||
template<class SerialPort, class Settings>
|
||||
DataByte MidiInterface<SerialPort, Settings>::getData1() const
|
||||
inline DataByte MidiInterface<SerialPort, Settings>::getData1() const
|
||||
{
|
||||
return mMessage.data1;
|
||||
}
|
||||
|
||||
/*! \brief Get the second data byte of the last received message. */
|
||||
template<class SerialPort, class Settings>
|
||||
DataByte MidiInterface<SerialPort, Settings>::getData2() const
|
||||
inline DataByte MidiInterface<SerialPort, Settings>::getData2() const
|
||||
{
|
||||
return mMessage.data2;
|
||||
}
|
||||
|
|
@ -887,7 +861,7 @@ DataByte MidiInterface<SerialPort, Settings>::getData2() const
|
|||
@see getSysExArrayLength to get the array's length in bytes.
|
||||
*/
|
||||
template<class SerialPort, class Settings>
|
||||
const byte* MidiInterface<SerialPort, Settings>::getSysExArray() const
|
||||
inline const byte* MidiInterface<SerialPort, Settings>::getSysExArray() const
|
||||
{
|
||||
return mMessage.sysexArray;
|
||||
}
|
||||
|
|
@ -898,16 +872,14 @@ const byte* MidiInterface<SerialPort, Settings>::getSysExArray() const
|
|||
\return The array's length, in bytes.
|
||||
*/
|
||||
template<class SerialPort, class Settings>
|
||||
unsigned MidiInterface<SerialPort, Settings>::getSysExArrayLength() const
|
||||
inline unsigned MidiInterface<SerialPort, Settings>::getSysExArrayLength() const
|
||||
{
|
||||
static const unsigned maxSize = Settings::SysExArraySize;
|
||||
const unsigned size = (unsigned(mMessage.data2) << 8) | mMessage.data1;
|
||||
return (size > maxSize) ? maxSize : size;
|
||||
return mMessage.getSysExSize();
|
||||
}
|
||||
|
||||
/*! \brief Check if a valid message is stored in the structure. */
|
||||
template<class SerialPort, class Settings>
|
||||
bool MidiInterface<SerialPort, Settings>::check() const
|
||||
inline bool MidiInterface<SerialPort, Settings>::check() const
|
||||
{
|
||||
return mMessage.valid;
|
||||
}
|
||||
|
|
@ -915,7 +887,7 @@ bool MidiInterface<SerialPort, Settings>::check() const
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
template<class SerialPort, class Settings>
|
||||
Channel MidiInterface<SerialPort, Settings>::getInputChannel() const
|
||||
inline Channel MidiInterface<SerialPort, Settings>::getInputChannel() const
|
||||
{
|
||||
return mInputChannel;
|
||||
}
|
||||
|
|
@ -925,7 +897,7 @@ Channel MidiInterface<SerialPort, Settings>::getInputChannel() const
|
|||
if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input.
|
||||
*/
|
||||
template<class SerialPort, class Settings>
|
||||
void MidiInterface<SerialPort, Settings>::setInputChannel(Channel inChannel)
|
||||
inline void MidiInterface<SerialPort, Settings>::setInputChannel(Channel inChannel)
|
||||
{
|
||||
mInputChannel = inChannel;
|
||||
}
|
||||
|
|
@ -980,8 +952,6 @@ bool MidiInterface<SerialPort, Settings>::isChannelMessage(MidiType inType)
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#if MIDI_USE_CALLBACKS
|
||||
|
||||
/*! \addtogroup callbacks
|
||||
@{
|
||||
*/
|
||||
|
|
@ -993,7 +963,7 @@ template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settin
|
|||
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; }
|
||||
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; }
|
||||
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; }
|
||||
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::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, class Settings> void MidiInterface<SerialPort, Settings>::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; }
|
||||
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSongPosition(void (*fptr)(unsigned beats)) { mSongPositionCallback = fptr; }
|
||||
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; }
|
||||
|
|
@ -1066,7 +1036,7 @@ void MidiInterface<SerialPort, Settings>::launchCallback()
|
|||
case AfterTouchChannel: if (mAfterTouchChannelCallback != 0) mAfterTouchChannelCallback(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
|
||||
case TimeCodeQuarterFrame: if (mTimeCodeQuarterFrameCallback != 0) mTimeCodeQuarterFrameCallback(mMessage.data1); break;
|
||||
|
|
@ -1081,19 +1051,12 @@ void MidiInterface<SerialPort, Settings>::launchCallback()
|
|||
}
|
||||
}
|
||||
|
||||
#endif // MIDI_USE_CALLBACKS
|
||||
|
||||
/*! @} */ // End of doc group MIDI Input
|
||||
|
||||
#endif // MIDI_BUILD_INPUT
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Thru
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU)
|
||||
|
||||
/*! \addtogroup thru
|
||||
@{
|
||||
*/
|
||||
|
|
@ -1238,8 +1201,6 @@ void MidiInterface<SerialPort, Settings>::thruFilter(Channel inChannel)
|
|||
}
|
||||
}
|
||||
|
||||
#endif // MIDI_BUILD_THRU
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
END_MIDI_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -24,8 +24,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "midi_Namespace.h"
|
||||
#include "midi_Settings.h"
|
||||
|
||||
#if ARDUINO
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
typedef uint8_t byte;
|
||||
#endif
|
||||
|
||||
BEGIN_MIDI_NAMESPACE
|
||||
|
||||
|
|
@ -40,7 +45,6 @@ BEGIN_MIDI_NAMESPACE
|
|||
// -----------------------------------------------------------------------------
|
||||
// Type definitions
|
||||
|
||||
typedef uint8_t byte;
|
||||
typedef byte StatusByte;
|
||||
typedef byte DataByte;
|
||||
typedef byte Channel;
|
||||
|
|
@ -155,48 +159,6 @@ enum MidiControlChangeNumber
|
|||
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.
|
||||
|
|
@ -207,6 +169,19 @@ struct Message
|
|||
#define MIDI_CREATE_INSTANCE(Type, SerialPort, Name) \
|
||||
midi::MidiInterface<Type> Name((Type&)SerialPort);
|
||||
|
||||
#if defined(ARDUINO_SAM_DUE) || defined(USBCON)
|
||||
// Leonardo, Due and other USB boards use Serial1 by default.
|
||||
#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_CREATE_DEFAULT_INSTANCE() \
|
||||
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, MIDI);
|
||||
#endif
|
||||
|
||||
/*! \brief Create an instance of the library attached to a serial port with
|
||||
custom settings.
|
||||
@see DefaultSettings
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
/*!
|
||||
* @file midi_Message.h
|
||||
* Project Arduino MIDI Library
|
||||
* @brief MIDI Library for the Arduino - Message struct definition
|
||||
* @version 4.1
|
||||
* @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
|
||||
|
|
@ -23,47 +23,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "midi_Namespace.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.
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#include "midi_Defs.h"
|
||||
|
||||
// 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
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 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.
|
||||
#define MIDI_BUILD_INPUT 1
|
||||
#define MIDI_BUILD_OUTPUT 1
|
||||
#define MIDI_BUILD_THRU 1
|
||||
#define MIDI_USE_CALLBACKS 1
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -82,11 +51,33 @@ BEGIN_MIDI_NAMESPACE
|
|||
*/
|
||||
struct DefaultSettings
|
||||
{
|
||||
static const bool UseRunningStatus = true;
|
||||
static const bool HandleNullVelocityNoteOnAsNoteOff = true;
|
||||
static const bool Use1ByteParsing = true;
|
||||
static const unsigned BaudRate = 31250;
|
||||
static const unsigned SysExArraySize = 128;
|
||||
/*! 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
|
||||
|
|
|
|||
Loading…
Reference in New Issue