mirror of https://github.com/AxioDL/boo.git
Add MIDI interface classes
This commit is contained in:
parent
77507459cc
commit
7756fcaf76
|
@ -191,6 +191,9 @@ add_library(boo
|
|||
lib/audiodev/AudioSubmix.hpp
|
||||
lib/audiodev/AudioSubmix.cpp
|
||||
lib/audiodev/IAudioMix.hpp
|
||||
lib/audiodev/MIDIEncoder.cpp
|
||||
lib/audiodev/MIDIDecoder.cpp
|
||||
lib/audiodev/MIDICommon.hpp
|
||||
include/boo/inputdev/IHIDListener.hpp
|
||||
include/boo/IGraphicsContext.hpp
|
||||
include/boo/graphicsdev/IGraphicsDataFactory.hpp
|
||||
|
@ -198,6 +201,9 @@ add_library(boo
|
|||
include/boo/audiodev/IAudioSubmix.hpp
|
||||
include/boo/audiodev/IAudioVoice.hpp
|
||||
include/boo/audiodev/IMIDIPort.hpp
|
||||
include/boo/audiodev/IMIDIReader.hpp
|
||||
include/boo/audiodev/MIDIEncoder.hpp
|
||||
include/boo/audiodev/MIDIDecoder.hpp
|
||||
include/boo/audiodev/IAudioVoiceEngine.hpp
|
||||
include/boo/IWindow.hpp
|
||||
include/boo/IApplication.hpp
|
||||
|
|
|
@ -45,7 +45,7 @@ struct IAudioVoiceEngine
|
|||
virtual void pumpAndMixVoices()=0;
|
||||
|
||||
/** Get list of MIDI devices found on system */
|
||||
virtual std::vector<std::string> enumerateMIDIDevices() const=0;
|
||||
virtual std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices() const=0;
|
||||
|
||||
/** Create ad-hoc MIDI in port and register with system */
|
||||
virtual std::unique_ptr<IMIDIIn> newVirtualMIDIIn()=0;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define BOO_IMIDIPORT_HPP
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef BOO_IMIDIREADER_HPP
|
||||
#define BOO_IMIDIREADER_HPP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
class IMIDIReader
|
||||
{
|
||||
public:
|
||||
virtual void noteOff(uint8_t chan, uint8_t key, uint8_t velocity)=0;
|
||||
virtual void noteOn(uint8_t chan, uint8_t key, uint8_t velocity)=0;
|
||||
virtual void notePressure(uint8_t chan, uint8_t key, uint8_t pressure)=0;
|
||||
virtual void controlChange(uint8_t chan, uint8_t control, uint8_t value)=0;
|
||||
virtual void programChange(uint8_t chan, uint8_t program)=0;
|
||||
virtual void channelPressure(uint8_t chan, uint8_t pressure)=0;
|
||||
virtual void pitchBend(uint8_t chan, int16_t pitch)=0;
|
||||
|
||||
virtual void allSoundOff(uint8_t chan)=0;
|
||||
virtual void resetAllControllers(uint8_t chan)=0;
|
||||
virtual void localControl(uint8_t chan, bool on)=0;
|
||||
virtual void allNotesOff(uint8_t chan)=0;
|
||||
virtual void omniMode(uint8_t chan, bool on)=0;
|
||||
virtual void polyMode(uint8_t chan, bool on)=0;
|
||||
|
||||
virtual void sysex(const void* data, size_t len)=0;
|
||||
virtual void timeCodeQuarterFrame(uint8_t message, uint8_t value)=0;
|
||||
virtual void songPositionPointer(uint16_t pointer)=0;
|
||||
virtual void songSelect(uint8_t song)=0;
|
||||
virtual void tuneRequest()=0;
|
||||
|
||||
virtual void startSeq()=0;
|
||||
virtual void continueSeq()=0;
|
||||
virtual void stopSeq()=0;
|
||||
|
||||
virtual void reset()=0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // BOO_IMIDIREADER_HPP
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef BOO_MIDIDECODER_HPP
|
||||
#define BOO_MIDIDECODER_HPP
|
||||
|
||||
#include "boo/audiodev/IMIDIReader.hpp"
|
||||
#include "boo/audiodev/IMIDIPort.hpp"
|
||||
#include <functional>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
class MIDIDecoder
|
||||
{
|
||||
IMIDIReader& m_out;
|
||||
uint8_t m_status = 0;
|
||||
|
||||
struct ReadController
|
||||
{
|
||||
IMIDIIn& m_in;
|
||||
bool readByte(uint8_t& a);
|
||||
bool read2Bytes(uint8_t& a, uint8_t& b);
|
||||
bool readBuffer(void* buf, size_t len);
|
||||
ReadController(IMIDIIn& in) : m_in(in) {}
|
||||
} m_readControl;
|
||||
uint32_t _readContinuedValue(uint8_t a);
|
||||
public:
|
||||
MIDIDecoder(IMIDIIn& in, IMIDIReader& out) : m_readControl(in), m_out(out) {}
|
||||
bool receiveBytes();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // BOO_MIDIDECODER_HPP
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef BOO_MIDIENCODER_HPP
|
||||
#define BOO_MIDIENCODER_HPP
|
||||
|
||||
#include "boo/audiodev/IMIDIReader.hpp"
|
||||
#include "boo/audiodev/IMIDIPort.hpp"
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
template <class Sender>
|
||||
class MIDIEncoder : public IMIDIReader
|
||||
{
|
||||
Sender& m_sender;
|
||||
uint8_t m_status = 0;
|
||||
void _sendMessage(const uint8_t* data, size_t len);
|
||||
void _sendContinuedValue(uint32_t val);
|
||||
public:
|
||||
MIDIEncoder(Sender& sender) : m_sender(sender) {}
|
||||
|
||||
void noteOff(uint8_t chan, uint8_t key, uint8_t velocity);
|
||||
void noteOn(uint8_t chan, uint8_t key, uint8_t velocity);
|
||||
void notePressure(uint8_t chan, uint8_t key, uint8_t pressure);
|
||||
void controlChange(uint8_t chan, uint8_t control, uint8_t value);
|
||||
void programChange(uint8_t chan, uint8_t program);
|
||||
void channelPressure(uint8_t chan, uint8_t pressure);
|
||||
void pitchBend(uint8_t chan, int16_t pitch);
|
||||
|
||||
void allSoundOff(uint8_t chan);
|
||||
void resetAllControllers(uint8_t chan);
|
||||
void localControl(uint8_t chan, bool on);
|
||||
void allNotesOff(uint8_t chan);
|
||||
void omniMode(uint8_t chan, bool on);
|
||||
void polyMode(uint8_t chan, bool on);
|
||||
|
||||
void sysex(const void* data, size_t len);
|
||||
void timeCodeQuarterFrame(uint8_t message, uint8_t value);
|
||||
void songPositionPointer(uint16_t pointer);
|
||||
void songSelect(uint8_t song);
|
||||
void tuneRequest();
|
||||
|
||||
void startSeq();
|
||||
void continueSeq();
|
||||
void stopSeq();
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // BOO_MIDIENCODER_HPP
|
|
@ -320,9 +320,9 @@ struct ALSAAudioVoiceEngine : BaseAudioVoiceEngine
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> enumerateMIDIDevices() const
|
||||
std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices() const
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
std::vector<std::pair<std::string, std::string>> ret;
|
||||
int status;
|
||||
int card = -1; /* use -1 to prime the pump of iterating through card list */
|
||||
|
||||
|
@ -350,7 +350,8 @@ struct ALSAAudioVoiceEngine : BaseAudioVoiceEngine
|
|||
snd_rawmidi_info_t *info;
|
||||
snd_rawmidi_info_alloca(&info);
|
||||
snd_rawmidi_info_set_device(info, device);
|
||||
ret.push_back(snd_rawmidi_info_get_name(info));
|
||||
ret.push_back(std::make_pair(snd_rawmidi_info_get_id(info),
|
||||
snd_rawmidi_info_get_name(info)));
|
||||
}
|
||||
} while (device >= 0);
|
||||
|
||||
|
@ -370,6 +371,7 @@ struct ALSAAudioVoiceEngine : BaseAudioVoiceEngine
|
|||
MIDIIn(snd_rawmidi_t* midi, bool virt)
|
||||
: m_midi(midi), m_virtual(virt) {}
|
||||
|
||||
~MIDIIn() {snd_rawmidi_close(m_midi);}
|
||||
bool isVirtual() const {return m_virtual;}
|
||||
std::string description() const
|
||||
{
|
||||
|
@ -385,35 +387,130 @@ struct ALSAAudioVoiceEngine : BaseAudioVoiceEngine
|
|||
}
|
||||
};
|
||||
|
||||
struct MIDIOut : public IMIDIOut
|
||||
{
|
||||
snd_rawmidi_t* m_midi;
|
||||
bool m_virtual;
|
||||
MIDIOut(snd_rawmidi_t* midi, bool virt)
|
||||
: m_midi(midi), m_virtual(virt) {}
|
||||
|
||||
~MIDIOut() {snd_rawmidi_close(m_midi);}
|
||||
bool isVirtual() const {return m_virtual;}
|
||||
std::string description() const
|
||||
{
|
||||
snd_rawmidi_info_t* info;
|
||||
snd_rawmidi_info_alloca(&info);
|
||||
snd_rawmidi_info(m_midi, info);
|
||||
std::string ret = snd_rawmidi_info_get_name(info);
|
||||
return ret;
|
||||
}
|
||||
size_t send(const void* buf, size_t len) const
|
||||
{
|
||||
return std::max(0l, snd_rawmidi_write(m_midi, buf, len));
|
||||
}
|
||||
};
|
||||
|
||||
struct MIDIInOut : public IMIDIInOut
|
||||
{
|
||||
snd_rawmidi_t* m_midiIn;
|
||||
snd_rawmidi_t* m_midiOut;
|
||||
bool m_virtual;
|
||||
MIDIInOut(snd_rawmidi_t* midiIn, snd_rawmidi_t* midiOut, bool virt)
|
||||
: m_midiIn(midiIn), m_midiOut(midiOut), m_virtual(virt) {}
|
||||
|
||||
~MIDIInOut()
|
||||
{
|
||||
snd_rawmidi_close(m_midiIn);
|
||||
snd_rawmidi_close(m_midiOut);
|
||||
}
|
||||
bool isVirtual() const {return m_virtual;}
|
||||
std::string description() const
|
||||
{
|
||||
snd_rawmidi_info_t* info;
|
||||
snd_rawmidi_info_alloca(&info);
|
||||
snd_rawmidi_info(m_midiIn, info);
|
||||
std::string ret = snd_rawmidi_info_get_name(info);
|
||||
return ret;
|
||||
}
|
||||
size_t receive(void* buf, size_t len) const
|
||||
{
|
||||
return std::max(0l, snd_rawmidi_read(m_midiOut, buf, len));
|
||||
}
|
||||
size_t send(const void* buf, size_t len) const
|
||||
{
|
||||
return std::max(0l, snd_rawmidi_write(m_midiOut, buf, len));
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<IMIDIIn> newVirtualMIDIIn()
|
||||
{
|
||||
int status;
|
||||
snd_rawmidi_t* midi;
|
||||
status = snd_rawmidi_open(&midi, nullptr, "virtual", 0);
|
||||
status = snd_rawmidi_open(&midi, nullptr, "virtual", SND_RAWMIDI_NONBLOCK);
|
||||
if (status)
|
||||
return {};
|
||||
|
||||
return std::make_unique<MIDIIn>(midi, true);
|
||||
}
|
||||
|
||||
std::unique_ptr<IMIDIOut> newVirtualMIDIOut()
|
||||
{
|
||||
int status;
|
||||
snd_rawmidi_t* midi;
|
||||
status = snd_rawmidi_open(nullptr, &midi, "virtual", SND_RAWMIDI_NONBLOCK);
|
||||
if (status)
|
||||
return {};
|
||||
return std::make_unique<MIDIOut>(midi, true);
|
||||
}
|
||||
|
||||
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut()
|
||||
{
|
||||
int status;
|
||||
snd_rawmidi_t* midiIn;
|
||||
snd_rawmidi_t* midiOut;
|
||||
status = snd_rawmidi_open(&midiIn, &midiOut, "virtual", SND_RAWMIDI_NONBLOCK);
|
||||
if (status)
|
||||
return {};
|
||||
return std::make_unique<MIDIInOut>(midiIn, midiOut, true);
|
||||
}
|
||||
|
||||
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name)
|
||||
{
|
||||
int status;
|
||||
char path[128];
|
||||
snprintf(path, 128, "hw:%s", name);
|
||||
|
||||
snd_rawmidi_t* midi;
|
||||
status = snd_rawmidi_open(&midi, nullptr, path, SND_RAWMIDI_NONBLOCK);
|
||||
if (status)
|
||||
return {};
|
||||
return std::make_unique<MIDIIn>(midi, true);
|
||||
}
|
||||
|
||||
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name)
|
||||
{
|
||||
int status;
|
||||
char path[128];
|
||||
snprintf(path, 128, "hw:%s", name);
|
||||
|
||||
snd_rawmidi_t* midi;
|
||||
status = snd_rawmidi_open(nullptr, &midi, path, SND_RAWMIDI_NONBLOCK);
|
||||
if (status)
|
||||
return {};
|
||||
return std::make_unique<MIDIOut>(midi, true);
|
||||
}
|
||||
|
||||
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name)
|
||||
{
|
||||
int status;
|
||||
char path[128];
|
||||
snprintf(path, 128, "hw:%s", name);
|
||||
|
||||
snd_rawmidi_t* midiIn;
|
||||
snd_rawmidi_t* midiOut;
|
||||
status = snd_rawmidi_open(&midiIn, &midiOut, path, SND_RAWMIDI_NONBLOCK);
|
||||
if (status)
|
||||
return {};
|
||||
return std::make_unique<MIDIInOut>(midiIn, midiOut, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef BOO_MIDICOMMON_HPP
|
||||
#define BOO_MIDICOMMON_HPP
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
enum class Status
|
||||
{
|
||||
NoteOff = 0x80,
|
||||
NoteOn = 0x90,
|
||||
NotePressure = 0xA0,
|
||||
ControlChange = 0xB0,
|
||||
ProgramChange = 0xC0,
|
||||
ChannelPressure = 0xD0,
|
||||
PitchBend = 0xE0,
|
||||
SysEx = 0xF0,
|
||||
TimecodeQuarterFrame = 0xF1,
|
||||
SongPositionPointer = 0xF2,
|
||||
SongSelect = 0xF3,
|
||||
TuneRequest = 0xF6,
|
||||
SysExTerm = 0xF7,
|
||||
TimingClock = 0xF8,
|
||||
Start = 0xFA,
|
||||
Continue = 0xFB,
|
||||
Stop = 0xFC,
|
||||
ActiveSensing = 0xFE,
|
||||
Reset = 0xFF,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // BOO_MIDICOMMON_HPP
|
|
@ -0,0 +1,181 @@
|
|||
#include "boo/audiodev/MIDIDecoder.hpp"
|
||||
#include "MIDICommon.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
static inline uint8_t clamp7(uint8_t val) {return std::max(0, std::min(127, int(val)));}
|
||||
|
||||
bool MIDIDecoder::ReadController::readByte(uint8_t& a)
|
||||
{
|
||||
return m_in.receive(&a, 1) != 0;
|
||||
}
|
||||
|
||||
bool MIDIDecoder::ReadController::read2Bytes(uint8_t& a, uint8_t& b)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
int len = m_in.receive(buf, 2);
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
return len > 1;
|
||||
}
|
||||
|
||||
bool MIDIDecoder::ReadController::readBuffer(void* buf, size_t len)
|
||||
{
|
||||
return m_in.receive(buf, len) == len;
|
||||
}
|
||||
|
||||
uint32_t MIDIDecoder::_readContinuedValue(uint8_t a)
|
||||
{
|
||||
uint32_t ret = a & 0x7f;
|
||||
|
||||
if (a & 0x80)
|
||||
{
|
||||
ret <<= 7;
|
||||
bool good = m_readControl.readByte(a);
|
||||
if (!good)
|
||||
return ret;
|
||||
ret |= a & 0x7f;
|
||||
|
||||
if (a & 0x80)
|
||||
{
|
||||
ret <<= 7;
|
||||
good = m_readControl.readByte(a);
|
||||
if (!good)
|
||||
return ret;
|
||||
ret |= a & 0x7f;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MIDIDecoder::receiveBytes()
|
||||
{
|
||||
uint8_t a, b;
|
||||
bool good = m_readControl.read2Bytes(a, b);
|
||||
if (!good)
|
||||
return false;
|
||||
|
||||
if (a & 0x80)
|
||||
m_status = a;
|
||||
else
|
||||
b = a;
|
||||
|
||||
uint8_t chan = m_status & 0xf;
|
||||
switch (Status(m_status & 0xf0))
|
||||
{
|
||||
case Status::NoteOff:
|
||||
{
|
||||
good = m_readControl.read2Bytes(a, b);
|
||||
if (!good)
|
||||
return false;
|
||||
m_out.noteOff(chan, clamp7(a), clamp7(b));
|
||||
break;
|
||||
}
|
||||
case Status::NoteOn:
|
||||
{
|
||||
good = m_readControl.read2Bytes(a, b);
|
||||
if (!good)
|
||||
return false;
|
||||
m_out.noteOn(chan, clamp7(a), clamp7(b));
|
||||
break;
|
||||
}
|
||||
case Status::NotePressure:
|
||||
{
|
||||
good = m_readControl.read2Bytes(a, b);
|
||||
if (!good)
|
||||
return false;
|
||||
m_out.notePressure(chan, clamp7(a), clamp7(b));
|
||||
break;
|
||||
}
|
||||
case Status::ControlChange:
|
||||
{
|
||||
good = m_readControl.read2Bytes(a, b);
|
||||
if (!good)
|
||||
return false;
|
||||
m_out.controlChange(chan, clamp7(a), clamp7(b));
|
||||
break;
|
||||
}
|
||||
case Status::ProgramChange:
|
||||
{
|
||||
m_out.programChange(chan, clamp7(b));
|
||||
break;
|
||||
}
|
||||
case Status::ChannelPressure:
|
||||
{
|
||||
m_out.channelPressure(chan, clamp7(b));
|
||||
break;
|
||||
}
|
||||
case Status::PitchBend:
|
||||
{
|
||||
good = m_readControl.read2Bytes(a, b);
|
||||
if (!good)
|
||||
return false;
|
||||
m_out.pitchBend(chan, clamp7(b) * 128 + clamp7(a));
|
||||
break;
|
||||
}
|
||||
case Status::SysEx:
|
||||
{
|
||||
switch (Status(m_status & 0xff))
|
||||
{
|
||||
case Status::SysEx:
|
||||
{
|
||||
uint32_t len = _readContinuedValue(a);
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
|
||||
if (!m_readControl.readBuffer(buf.get(), len))
|
||||
return false;
|
||||
m_out.sysex(buf.get(), len);
|
||||
break;
|
||||
}
|
||||
case Status::TimecodeQuarterFrame:
|
||||
{
|
||||
good = m_readControl.read2Bytes(a, b);
|
||||
if (!good)
|
||||
return false;
|
||||
m_out.timeCodeQuarterFrame(a >> 4 & 0x7, a & 0xf);
|
||||
break;
|
||||
}
|
||||
case Status::SongPositionPointer:
|
||||
{
|
||||
good = m_readControl.read2Bytes(a, b);
|
||||
if (!good)
|
||||
return false;
|
||||
m_out.songPositionPointer(clamp7(b) * 128 + clamp7(a));
|
||||
break;
|
||||
}
|
||||
case Status::SongSelect:
|
||||
{
|
||||
m_out.songSelect(clamp7(b));
|
||||
break;
|
||||
}
|
||||
case Status::TuneRequest:
|
||||
m_out.tuneRequest();
|
||||
break;
|
||||
case Status::Start:
|
||||
m_out.startSeq();
|
||||
break;
|
||||
case Status::Continue:
|
||||
m_out.continueSeq();
|
||||
break;
|
||||
case Status::Stop:
|
||||
m_out.stopSeq();
|
||||
break;
|
||||
case Status::Reset:
|
||||
m_out.reset();
|
||||
break;
|
||||
case Status::SysExTerm:
|
||||
case Status::TimingClock:
|
||||
case Status::ActiveSensing:
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
#include "boo/audiodev/MIDIEncoder.hpp"
|
||||
#include "MIDICommon.hpp"
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::_sendMessage(const uint8_t* data, size_t len)
|
||||
{
|
||||
if (data[0] == m_status)
|
||||
m_sender.send(data + 1, len - 1);
|
||||
else
|
||||
{
|
||||
if (data[0] & 0x80)
|
||||
m_status = data[0];
|
||||
m_sender.send(data, len);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::_sendContinuedValue(uint32_t val)
|
||||
{
|
||||
uint32_t send[3] = {};
|
||||
uint32_t* ptr = nullptr;
|
||||
if (val >= 0x4000)
|
||||
{
|
||||
ptr = &send[0];
|
||||
send[0] = (val / 0x4000) & 0x7f;
|
||||
val &= 0x3fff;
|
||||
}
|
||||
|
||||
if (val >= 0x80)
|
||||
{
|
||||
if (!ptr)
|
||||
ptr = &send[1];
|
||||
send[1] = (val / 0x80) & 0x7f;
|
||||
}
|
||||
|
||||
if (!ptr)
|
||||
ptr = &send[2];
|
||||
send[2] = val & 0x7f;
|
||||
|
||||
m_sender.send(ptr, 3 - (ptr - send));
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::noteOff(uint8_t chan, uint8_t key, uint8_t velocity)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::NoteOff) | (chan & 0xf)),
|
||||
uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::noteOn(uint8_t chan, uint8_t key, uint8_t velocity)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::NoteOn) | (chan & 0xf)),
|
||||
uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::notePressure(uint8_t chan, uint8_t key, uint8_t pressure)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::NotePressure) | (chan & 0xf)),
|
||||
uint8_t(key & 0x7f), uint8_t(pressure & 0x7f)};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::controlChange(uint8_t chan, uint8_t control, uint8_t value)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
|
||||
uint8_t(control & 0x7f), uint8_t(value & 0x7f)};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::programChange(uint8_t chan, uint8_t program)
|
||||
{
|
||||
uint8_t cmd[2] = {uint8_t(int(Status::ProgramChange) | (chan & 0xf)),
|
||||
uint8_t(program & 0x7f)};
|
||||
_sendMessage(cmd, 2);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::channelPressure(uint8_t chan, uint8_t pressure)
|
||||
{
|
||||
uint8_t cmd[2] = {uint8_t(int(Status::ChannelPressure) | (chan & 0xf)),
|
||||
uint8_t(pressure & 0x7f)};
|
||||
_sendMessage(cmd, 2);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::pitchBend(uint8_t chan, int16_t pitch)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::PitchBend) | (chan & 0xf)),
|
||||
uint8_t((pitch % 128) & 0x7f), uint8_t((pitch / 128) & 0x7f)};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::allSoundOff(uint8_t chan)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
|
||||
120, 0};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::resetAllControllers(uint8_t chan)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
|
||||
121, 0};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::localControl(uint8_t chan, bool on)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
|
||||
122, uint8_t(on ? 127 : 0)};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::allNotesOff(uint8_t chan)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
|
||||
123, 0};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::omniMode(uint8_t chan, bool on)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
|
||||
uint8_t(on ? 125 : 124), 0};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::polyMode(uint8_t chan, bool on)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
|
||||
uint8_t(on ? 127 : 126), 0};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::sysex(const void* data, size_t len)
|
||||
{
|
||||
uint8_t cmd = uint8_t(Status::SysEx);
|
||||
_sendMessage(&cmd, 1);
|
||||
_sendContinuedValue(len);
|
||||
m_sender.send(data, len);
|
||||
cmd = uint8_t(Status::SysExTerm);
|
||||
_sendMessage(&cmd, 1);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::timeCodeQuarterFrame(uint8_t message, uint8_t value)
|
||||
{
|
||||
uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)),
|
||||
uint8_t((message & 0x7 << 4) | (value & 0xf))};
|
||||
_sendMessage(cmd, 2);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::songPositionPointer(uint16_t pointer)
|
||||
{
|
||||
uint8_t cmd[3] = {uint8_t(int(Status::SongPositionPointer)),
|
||||
uint8_t((pointer % 128) & 0x7f), uint8_t((pointer / 128) & 0x7f)};
|
||||
_sendMessage(cmd, 3);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::songSelect(uint8_t song)
|
||||
{
|
||||
uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)),
|
||||
uint8_t(song & 0x7f)};
|
||||
_sendMessage(cmd, 2);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::tuneRequest()
|
||||
{
|
||||
uint8_t cmd = uint8_t(Status::TuneRequest);
|
||||
_sendMessage(&cmd, 1);
|
||||
}
|
||||
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::startSeq()
|
||||
{
|
||||
uint8_t cmd = uint8_t(Status::Start);
|
||||
_sendMessage(&cmd, 1);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::continueSeq()
|
||||
{
|
||||
uint8_t cmd = uint8_t(Status::Continue);
|
||||
_sendMessage(&cmd, 1);
|
||||
}
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::stopSeq()
|
||||
{
|
||||
uint8_t cmd = uint8_t(Status::Stop);
|
||||
_sendMessage(&cmd, 1);
|
||||
}
|
||||
|
||||
|
||||
template <class Sender>
|
||||
void MIDIEncoder<Sender>::reset()
|
||||
{
|
||||
uint8_t cmd = uint8_t(Status::Reset);
|
||||
_sendMessage(&cmd, 1);
|
||||
}
|
||||
|
||||
template class MIDIEncoder<IMIDIOut>;
|
||||
template class MIDIEncoder<IMIDIInOut>;
|
||||
|
||||
}
|
Loading…
Reference in New Issue