using pxt-midi
This commit is contained in:
Родитель
5fbae8a3bc
Коммит
9a4e93e108
|
@ -342,6 +342,11 @@ public:
|
|||
*/
|
||||
void sendSystemExclusive(uint8_t * sysex, uint16_t length);
|
||||
|
||||
|
||||
void sendMidiMessage(uint8_t data0);
|
||||
void sendMidiMessage(uint8_t data0, uint8_t data1);
|
||||
void sendMidiMessage(uint8_t data0, uint8_t data1, uint8_t data2);
|
||||
|
||||
private:
|
||||
uint16_t sysExBufferPos;
|
||||
uint8_t sysExBuffer[128];
|
||||
|
@ -388,10 +393,6 @@ private:
|
|||
void (*onSongPositionPointer)(uint16_t);
|
||||
void (*onSystemExclusive)(uint8_t *, uint16_t, bool);
|
||||
|
||||
void sendMidiMessage(uint8_t data0);
|
||||
void sendMidiMessage(uint8_t data0, uint8_t data1);
|
||||
void sendMidiMessage(uint8_t data0, uint8_t data1, uint8_t data2);
|
||||
|
||||
void onDataWritten(const GattWriteCallbackParams *params);
|
||||
};
|
||||
|
||||
|
|
30
README.md
30
README.md
|
@ -11,31 +11,25 @@ For another device like a smartphone to use any of the Bluetooth "services" whic
|
|||
|
||||
## Usage
|
||||
|
||||
This package allows the @boardname@ to act as a MIDI peripherical, like a piano. It requires to connect to a BLE MIDI device to receive the commands and play them. On iPhone/iPad, try [KORG Module Le](https://itunes.apple.com/us/app/korg-module-le/id1048875111) to play the piano with your @boardname@!
|
||||
This package allows the @boardname@ to act as a MIDI peripherical, like a piano. It requires to connect to a BLE MIDI device to receive the commands and play them.
|
||||
|
||||
### Example
|
||||
|
||||
This program plays all the notes from ``F#-0`` to ``F#-5``.
|
||||
Place a ``||bluetooth start midi service||`` block in your program to enable MDI over Bluetooth low energy.
|
||||
|
||||
```blocks
|
||||
bluetooth.startMidiService();
|
||||
```
|
||||
midi.startBluetoothService();
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
// blink the screen
|
||||
led.toggle(0, 0);
|
||||
// play note
|
||||
midi.noteOn(0x90, 400, 0x45);
|
||||
//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
|
||||
basic.pause(150);
|
||||
//Note on channel 1 (0x90), some note value (note), silent velocity (0x00):
|
||||
midi.noteOn(0x90, 400, 0x00);
|
||||
basic.pause(150);
|
||||
})
|
||||
```
|
||||
|
||||
This library uses the [MIDI package](pxt.microbit.org/pkg/microsoft/pxt-midi).
|
||||
Please refer to that project documentation for further details.
|
||||
|
||||
## Apps
|
||||
|
||||
* iPhone/iPad: [Apple GarageBand](https://itunes.apple.com/us/app/garageband/id408709785?mt=8)
|
||||
* iPhone/iPad: [KORG Module Le](https://itunes.apple.com/us/app/korg-module-le/id1048875111)
|
||||
|
||||
## Supported targets
|
||||
|
||||
* for PXT/microbit
|
||||
* for PXT/calliope
|
||||
|
||||
(The metadata above is needed for package search.)
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
namespace bluetooth {
|
||||
/**
|
||||
* Starts the MIDI service over Bluetooth and registers it as the MIDI transport.
|
||||
*/
|
||||
//% blockId=bluetooth_start_midi block="bluetooth start midi service"
|
||||
export function startMidiService() {
|
||||
function send(buffer: Buffer) {
|
||||
bluetooth.midiSendMessage(buffer);
|
||||
}
|
||||
midi.setInputTransport(send);
|
||||
bluetooth.midiSendMessage(pins.createBuffer(0));
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
MIDI_STATE_SIGNAL_3BYTES_3 = 4,
|
||||
MIDI_STATE_SIGNAL_SYSEX = 5,
|
||||
}
|
||||
declare namespace midi {
|
||||
declare namespace bluetooth {
|
||||
}
|
||||
|
||||
// Auto-generated. Do not edit. Really.
|
||||
|
|
190
midi.cpp
190
midi.cpp
|
@ -4,8 +4,7 @@ using namespace pxt;
|
|||
/**
|
||||
* A set of functions to send MIDI commands over Bluetooth
|
||||
*/
|
||||
//% color=#0082FB weight=96 icon="\uf294"
|
||||
namespace midi {
|
||||
namespace bluetooth {
|
||||
BluetoothMIDIService* pMidi;
|
||||
|
||||
BluetoothMIDIService* getMidi()
|
||||
|
@ -16,177 +15,22 @@ namespace midi {
|
|||
}
|
||||
|
||||
/**
|
||||
* Starts the MIDI service
|
||||
* Sends a MIDI message
|
||||
*/
|
||||
//% block
|
||||
void startBluetoothService() {
|
||||
getMidi();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Note On` event
|
||||
* @param channel 0-15
|
||||
* @param note 0-127
|
||||
* @param velocity 0-127
|
||||
*/
|
||||
//% block
|
||||
//% channel.min=0 channel.max=15 note.min=0 note.max=127 velocity.min=0 velocity.max=127
|
||||
void noteOn(uint8_t channel, uint8_t note, uint8_t velocity) {
|
||||
getMidi()->sendNoteOn(channel, note, velocity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Note Off` event
|
||||
* @param channel 0-15
|
||||
* @param note 0-127
|
||||
* @param velocity 0-127
|
||||
*/
|
||||
//% block
|
||||
//% channel.min=0 channel.max=15 note.min=0 note.max=127 velocity.min=0 velocity.max=127
|
||||
void noteOff(uint8_t channel, uint8_t note, uint8_t velocity) {
|
||||
getMidi()->sendNoteOff(channel, note, velocity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Tune Request` event
|
||||
*/
|
||||
//% block
|
||||
void tuneRequest() {
|
||||
getMidi()->sendTuneRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Timing Clock` event
|
||||
*/
|
||||
//% block
|
||||
void timingClock() {
|
||||
getMidi()->sendTimingClock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Start` event
|
||||
*/
|
||||
//% block
|
||||
void start() {
|
||||
getMidi()->sendStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Continue` event
|
||||
*/
|
||||
//% block
|
||||
void cont() {
|
||||
getMidi()->sendContinue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Stop` event
|
||||
*/
|
||||
//% block
|
||||
void sendStop() {
|
||||
getMidi()->sendReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Active Sensing` event
|
||||
*/
|
||||
//% block
|
||||
void sendActiveSensing() {
|
||||
getMidi()->sendReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Reset` event
|
||||
*/
|
||||
//% block
|
||||
void sendReset() {
|
||||
getMidi()->sendReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Program Change` event
|
||||
*
|
||||
* @param channel 0-15
|
||||
* @param program 0-127
|
||||
*/
|
||||
//% block channel.min=0 channel.max=15 program.min=0 program.max=127
|
||||
void programChange(uint8_t channel, uint8_t program) {
|
||||
getMidi()->sendProgramChange(channel, program);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Channel Aftertouch` event
|
||||
*
|
||||
* @param channel 0-15
|
||||
* @param pressure 0-127
|
||||
*/
|
||||
//% block channel.min=0 channel.max=15 channel.pressure=0 channel.pressure=127
|
||||
void channelAftertouch(uint8_t channel, uint8_t pressure) {
|
||||
getMidi()->sendChannelAftertouch(channel, pressure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Time Code Quarter Frame` event
|
||||
*
|
||||
* @param timing 0-127
|
||||
*/
|
||||
//% block timing.min=0 timing.max=127
|
||||
void timeCodeQuarterFrame(uint8_t timing) {
|
||||
getMidi()->sendTimeCodeQuarterFrame(timing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Song Select` event
|
||||
*
|
||||
* @param song 0-127
|
||||
*/
|
||||
//% block song.min=0 song.max=127
|
||||
void songSelect(uint8_t song) {
|
||||
getMidi()->sendSongSelect(song);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Polyphonic Aftertouch` event
|
||||
*
|
||||
* @param channel 0-15
|
||||
* @param note 0-127
|
||||
* @param pressure 0-127
|
||||
*/
|
||||
//% block channel.min=0 channel.max=15 note.min=0 note.max=127 pressure.min=0 pressure.max=127
|
||||
void polyphonicAftertouch(uint8_t channel, uint8_t note, uint8_t pressure) {
|
||||
getMidi()->sendPolyphonicAftertouch(channel, note, pressure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Control Change` event
|
||||
*
|
||||
* @param channel 0-15
|
||||
* @param func 0-127
|
||||
* @param value 0-127
|
||||
*/
|
||||
//% block channel.min=0 channel.max=15 func.min=0 func.max=127 value.min=0 value.max=127
|
||||
void controlChange(uint8_t channel, uint8_t func, uint8_t value) {
|
||||
getMidi()->sendControlChange(channel, func, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Pitch Wheel` event
|
||||
*
|
||||
* @param channel 0-15
|
||||
* @param amount 0-8192(center)-16383, eg: 8192
|
||||
*/
|
||||
//% block channel.min=0 channel.max=15 amount.min=0 amount.max=16383
|
||||
void pitchWheel(uint8_t channel, uint16_t amount) {
|
||||
getMidi()->sendPitchWheel(channel, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a `Song Position Pointer` event
|
||||
*
|
||||
* @param position 0-16383
|
||||
*/
|
||||
//% block position.min=0 position.max=16383
|
||||
void songPositionPointer(uint16_t position) {
|
||||
getMidi()->sendSongPositionPointer(position);
|
||||
//%
|
||||
void midiSendMessage(Buffer data) {
|
||||
BluetoothMIDIService* pMidi = getMidi();
|
||||
ManagedBuffer buf(data);
|
||||
switch(buf.length()) {
|
||||
case 1:
|
||||
pMidi->sendMidiMessage(buf[0]);
|
||||
break;
|
||||
case 2:
|
||||
pMidi->sendMidiMessage(buf[0], buf[1]);
|
||||
break;
|
||||
case 3:
|
||||
pMidi->sendMidiMessage(buf[0], buf[1], buf[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
4
pxt.json
4
pxt.json
|
@ -5,13 +5,15 @@
|
|||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"core": "*",
|
||||
"bluetooth": "*"
|
||||
"bluetooth": "*",
|
||||
"midi": "github:Microsoft/pxt-midi#v0.0.4"
|
||||
},
|
||||
"files": [
|
||||
"README.md",
|
||||
"BluetoothMIDIService.cpp",
|
||||
"BluetoothMIDIService.h",
|
||||
"midi.cpp",
|
||||
"bluetooth.ts",
|
||||
"shims.d.ts",
|
||||
"enums.d.ts"
|
||||
],
|
||||
|
|
|
@ -4,147 +4,14 @@
|
|||
/**
|
||||
* A set of functions to send MIDI commands over Bluetooth
|
||||
*/
|
||||
//% color=#0082FB weight=96 icon="\uf294"
|
||||
declare namespace midi {
|
||||
|
||||
declare namespace bluetooth {
|
||||
|
||||
/**
|
||||
* Starts the MIDI service
|
||||
* Sends a MIDI message
|
||||
*/
|
||||
//% block shim=midi::startBluetoothService
|
||||
function startBluetoothService(): void;
|
||||
|
||||
/**
|
||||
* Send a `Note On` event
|
||||
* @param channel 0-15
|
||||
* @param note 0-127
|
||||
* @param velocity 0-127
|
||||
*/
|
||||
//% block
|
||||
//% channel.min=0 channel.max=15 note.min=0 note.max=127 velocity.min=0 velocity.max=127 shim=midi::noteOn
|
||||
function noteOn(channel: uint8, note: uint8, velocity: uint8): void;
|
||||
|
||||
/**
|
||||
* Send a `Note Off` event
|
||||
* @param channel 0-15
|
||||
* @param note 0-127
|
||||
* @param velocity 0-127
|
||||
*/
|
||||
//% block
|
||||
//% channel.min=0 channel.max=15 note.min=0 note.max=127 velocity.min=0 velocity.max=127 shim=midi::noteOff
|
||||
function noteOff(channel: uint8, note: uint8, velocity: uint8): void;
|
||||
|
||||
/**
|
||||
* Send a `Tune Request` event
|
||||
*/
|
||||
//% block shim=midi::tuneRequest
|
||||
function tuneRequest(): void;
|
||||
|
||||
/**
|
||||
* Send a `Timing Clock` event
|
||||
*/
|
||||
//% block shim=midi::timingClock
|
||||
function timingClock(): void;
|
||||
|
||||
/**
|
||||
* Send a `Start` event
|
||||
*/
|
||||
//% block shim=midi::start
|
||||
function start(): void;
|
||||
|
||||
/**
|
||||
* Send a `Continue` event
|
||||
*/
|
||||
//% block shim=midi::cont
|
||||
function cont(): void;
|
||||
|
||||
/**
|
||||
* Send a `Stop` event
|
||||
*/
|
||||
//% block shim=midi::sendStop
|
||||
function sendStop(): void;
|
||||
|
||||
/**
|
||||
* Send a `Active Sensing` event
|
||||
*/
|
||||
//% block shim=midi::sendActiveSensing
|
||||
function sendActiveSensing(): void;
|
||||
|
||||
/**
|
||||
* Send a `Reset` event
|
||||
*/
|
||||
//% block shim=midi::sendReset
|
||||
function sendReset(): void;
|
||||
|
||||
/**
|
||||
* Send a `Program Change` event
|
||||
*
|
||||
* @param channel 0-15
|
||||
* @param program 0-127
|
||||
*/
|
||||
//% block channel.min=0 channel.max=15 program.min=0 program.max=127 shim=midi::programChange
|
||||
function programChange(channel: uint8, program: uint8): void;
|
||||
|
||||
/**
|
||||
* Send a `Channel Aftertouch` event
|
||||
*
|
||||
* @param channel 0-15
|
||||
* @param pressure 0-127
|
||||
*/
|
||||
//% block channel.min=0 channel.max=15 channel.pressure=0 channel.pressure=127 shim=midi::channelAftertouch
|
||||
function channelAftertouch(channel: uint8, pressure: uint8): void;
|
||||
|
||||
/**
|
||||
* Send a `Time Code Quarter Frame` event
|
||||
*
|
||||
* @param timing 0-127
|
||||
*/
|
||||
//% block timing.min=0 timing.max=127 shim=midi::timeCodeQuarterFrame
|
||||
function timeCodeQuarterFrame(timing: uint8): void;
|
||||
|
||||
/**
|
||||
* Send a `Song Select` event
|
||||
*
|
||||
* @param song 0-127
|
||||
*/
|
||||
//% block song.min=0 song.max=127 shim=midi::songSelect
|
||||
function songSelect(song: uint8): void;
|
||||
|
||||
/**
|
||||
* Send a `Polyphonic Aftertouch` event
|
||||
*
|
||||
* @param channel 0-15
|
||||
* @param note 0-127
|
||||
* @param pressure 0-127
|
||||
*/
|
||||
//% block channel.min=0 channel.max=15 note.min=0 note.max=127 pressure.min=0 pressure.max=127 shim=midi::polyphonicAftertouch
|
||||
function polyphonicAftertouch(channel: uint8, note: uint8, pressure: uint8): void;
|
||||
|
||||
/**
|
||||
* Send a `Control Change` event
|
||||
*
|
||||
* @param channel 0-15
|
||||
* @param func 0-127
|
||||
* @param value 0-127
|
||||
*/
|
||||
//% block channel.min=0 channel.max=15 func.min=0 func.max=127 value.min=0 value.max=127 shim=midi::controlChange
|
||||
function controlChange(channel: uint8, func: uint8, value: uint8): void;
|
||||
|
||||
/**
|
||||
* Send a `Pitch Wheel` event
|
||||
*
|
||||
* @param channel 0-15
|
||||
* @param amount 0-8192(center)-16383, eg: 8192
|
||||
*/
|
||||
//% block channel.min=0 channel.max=15 amount.min=0 amount.max=16383 shim=midi::pitchWheel
|
||||
function pitchWheel(channel: uint8, amount: uint16): void;
|
||||
|
||||
/**
|
||||
* Send a `Song Position Pointer` event
|
||||
*
|
||||
* @param position 0-16383
|
||||
*/
|
||||
//% block position.min=0 position.max=16383 shim=midi::songPositionPointer
|
||||
function songPositionPointer(position: uint16): void;
|
||||
//% shim=bluetooth::midiSendMessage
|
||||
function midiSendMessage(data: Buffer): void;
|
||||
}
|
||||
|
||||
// Auto-generated. Do not edit. Really.
|
||||
|
|
13
tests.ts
13
tests.ts
|
@ -4,19 +4,16 @@ bluetooth.onBluetoothConnected(() => {
|
|||
bluetooth.onBluetoothDisconnected(() => {
|
||||
basic.showString("D")
|
||||
})
|
||||
midi.startBluetoothService();
|
||||
bluetooth.startMidiService();
|
||||
basic.showString("S")
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
basic.clearScreen();
|
||||
// https://www.arduino.cc/en/tutorial/midi
|
||||
// play notes from F#-0 (0x1E) to F#-5 (0x5A):
|
||||
for (let note = 0x1E; note < 0x5A; note++) {
|
||||
let piano = midi.inputChannel(0);
|
||||
for (let note = 0x0; note < 0x5A; note++) {
|
||||
led.toggle(0, 0);
|
||||
//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
|
||||
midi.noteOn(0x90, note, 0x45);
|
||||
piano.noteOn(note);
|
||||
basic.pause(100);
|
||||
//Note on channel 1 (0x90), some note value (note), silent velocity (0x00):
|
||||
midi.noteOff(0x90, note, 0x00);
|
||||
piano.noteOff(note);
|
||||
basic.pause(100);
|
||||
}
|
||||
})
|
Загрузка…
Ссылка в новой задаче