这是indexloc提供的服务,不要输入任何密码
Skip to content

Commit 64da06c

Browse files
author
Michael Wilson
committed
Move examples to explainer
1 parent 423a5ee commit 64da06c

File tree

2 files changed

+224
-247
lines changed

2 files changed

+224
-247
lines changed

explainer.md

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
# Web MIDI API Explainer
2+
3+
## Examples of Web MIDI API Usage in JavaScript
4+
The following are some examples of common MIDI usage in JavaScript.
5+
6+
### Getting Access to the MIDI System
7+
This example shows how to request access to the MIDI system.
8+
9+
```js
10+
var midi = null; // global MIDIAccess object
11+
12+
function onMIDISuccess( midiAccess ) {
13+
console.log( "MIDI ready!" );
14+
midi = midiAccess; // store in the global (in real usage, would probably keep in an object instance)
15+
}
16+
17+
function onMIDIFailure(msg) {
18+
console.log( "Failed to get MIDI access - " + msg );
19+
}
20+
21+
navigator.requestMIDIAccess().then( onMIDISuccess, onMIDIFailure );
22+
```
23+
24+
### Requesting Access to the MIDI System with System Exclusive Support
25+
This example shows how to request access to the MIDI system, including the
26+
ability to send and receive System Exclusive messages.
27+
28+
```js
29+
var midi = null; // global MIDIAccess object
30+
31+
function onMIDISuccess( midiAccess ) {
32+
console.log( "MIDI ready!" );
33+
midi = midiAccess; // store in the global (in real usage, would probably keep in an object instance)
34+
}
35+
36+
function onMIDIFailure(msg) {
37+
console.log( "Failed to get MIDI access - " + msg );
38+
}
39+
40+
navigator.requestMIDIAccess( { sysex: true } ).then( onMIDISuccess, onMIDIFailure );
41+
```
42+
43+
### Listing Inputs and Outputs
44+
This example gets the list of the input and output ports and prints their
45+
information to the console log, using ES6 for...of notation.
46+
47+
```js
48+
function listInputsAndOutputs( midiAccess ) {
49+
for (var entry of midiAccess.inputs) {
50+
var input = entry[1];
51+
console.log( "Input port [type:'" + input.type + "'] id:'" + input.id +
52+
"' manufacturer:'" + input.manufacturer + "' name:'" + input.name +
53+
"' version:'" + input.version + "'" );
54+
}
55+
56+
for (var entry of midiAccess.outputs) {
57+
var output = entry[1];
58+
console.log( "Output port [type:'" + output.type + "'] id:'" + output.id +
59+
"' manufacturer:'" + output.manufacturer + "' name:'" + output.name +
60+
"' version:'" + output.version + "'" );
61+
}
62+
}
63+
```
64+
65+
### Handling MIDI Input
66+
This example prints incoming MIDI messages on a single arbitrary input port to
67+
the console log.
68+
69+
```js
70+
function onMIDIMessage( event ) {
71+
var str = "MIDI message received at timestamp " + event.timeStamp + "[" + event.data.length + " bytes]: ";
72+
for (var i=0; i<event.data.length; i++) {
73+
str += "0x" + event.data[i].toString(16) + " ";
74+
}
75+
console.log( str );
76+
}
77+
78+
function startLoggingMIDIInput( midiAccess, indexOfPort ) {
79+
midiAccess.inputs.forEach( function(entry) {entry.onmidimessage = onMIDIMessage;});
80+
}
81+
```
82+
83+
### Sending MIDI Messages to an Output Device
84+
This example sends a middle C note on message immediately on MIDI channel 1
85+
(MIDI channels are 0-indexed, but generally referred to as channels 1-16), and
86+
queues a corresponding note off message for 1 second later.
87+
88+
```js
89+
function sendMiddleC( midiAccess, portID ) {
90+
var noteOnMessage = [0x90, 60, 0x7f]; // note on, middle C, full velocity
91+
var output = midiAccess.outputs.get(portID);
92+
output.send( noteOnMessage ); //omitting the timestamp means send immediately.
93+
output.send( [0x80, 60, 0x40], window.performance.now() + 1000.0 ); // Inlined array creation- note off, middle C,
94+
// release velocity = 64, timestamp = now + 1000ms.
95+
}
96+
```
97+
98+
### A Simple Loopback
99+
This example loops all input messages on the first input port to the first
100+
output port - including System Exclusive messages.
101+
102+
```js
103+
var midi = null; // global MIDIAccess object
104+
var output = null;
105+
106+
function echoMIDIMessage( event ) {
107+
if (output) {
108+
output.send( event.data, event.timeStamp );
109+
}
110+
}
111+
112+
function onMIDISuccess( midiAccess ) {
113+
console.log( "MIDI ready!" );
114+
var input = midiAccess.inputs.entries().next();
115+
if (input)
116+
input.onmidimessage = echoMIDIMessage;
117+
output = midiAccess.outputs.values().next().value;
118+
if (!input || !output)
119+
console.log("Uh oh! Couldn't get i/o ports.");
120+
}
121+
122+
function onMIDIFailure(msg) {
123+
console.log( "Failed to get MIDI access - " + msg );
124+
}
125+
126+
navigator.requestMIDIAccess().then( onMIDISuccess, onMIDIFailure );
127+
```
128+
129+
### A Simple Monophonic Sine Wave MIDI Synthesizer
130+
This example listens to all input messages from all available input ports, and
131+
uses note messages to drive the envelope and frequency on a monophonic sine wave
132+
oscillator, creating a very simple synthesizer, using the Web Audio API. Note on
133+
and note off messages are supported, but sustain pedal, velocity and pitch bend
134+
are not. This sample is also hosted on <a href=
135+
"http://webaudiodemos.appspot.com/monosynth/index.html">webaudiodemos.appspot.com</a>.
136+
137+
```js
138+
var context=null; // the Web Audio "context" object
139+
var midiAccess=null; // the MIDIAccess object.
140+
var oscillator=null; // the single oscillator
141+
var envelope=null; // the envelope for the single oscillator
142+
var attack=0.05; // attack speed
143+
var release=0.05; // release speed
144+
var portamento=0.05; // portamento/glide speed
145+
var activeNotes = []; // the stack of actively-pressed keys
146+
147+
window.addEventListener('load', function() {
148+
// patch up prefixes
149+
window.AudioContext=window.AudioContext||window.webkitAudioContext;
150+
151+
context = new AudioContext();
152+
if (navigator.requestMIDIAccess)
153+
navigator.requestMIDIAccess().then( onMIDIInit, onMIDIReject );
154+
else
155+
alert("No MIDI support present in your browser. You're gonna have a bad time.")
156+
157+
// set up the basic oscillator chain, muted to begin with.
158+
oscillator = context.createOscillator();
159+
oscillator.frequency.setValueAtTime(110, 0);
160+
envelope = context.createGain();
161+
oscillator.connect(envelope);
162+
envelope.connect(context.destination);
163+
envelope.gain.value = 0.0; // Mute the sound
164+
oscillator.start(0); // Go ahead and start up the oscillator
165+
} );
166+
167+
function onMIDIInit(midi) {
168+
midiAccess = midi;
169+
170+
var haveAtLeastOneDevice=false;
171+
var inputs=midiAccess.inputs.values();
172+
for ( var input = inputs.next(); input &amp;& !input.done; input = inputs.next()) {
173+
input.value.onmidimessage = MIDIMessageEventHandler;
174+
haveAtLeastOneDevice = true;
175+
}
176+
if (!haveAtLeastOneDevice)
177+
alert("No MIDI input devices present. You're gonna have a bad time.");
178+
}
179+
180+
function onMIDIReject(err) {
181+
alert("The MIDI system failed to start. You're gonna have a bad time.");
182+
}
183+
184+
function MIDIMessageEventHandler(event) {
185+
// Mask off the lower nibble (MIDI channel, which we don't care about)
186+
switch (event.data[0] & 0xf0) {
187+
case 0x90:
188+
if (event.data[2]!=0) { // if velocity != 0, this is a note-on message
189+
noteOn(event.data[1]);
190+
return;
191+
}
192+
// if velocity == 0, fall thru: it's a note-off. MIDI's weird, y'all.
193+
case 0x80:
194+
noteOff(event.data[1]);
195+
return;
196+
}
197+
}
198+
199+
function frequencyFromNoteNumber( note ) {
200+
return 440 * Math.pow(2,(note-69)/12);
201+
}
202+
203+
function noteOn(noteNumber) {
204+
activeNotes.push( noteNumber );
205+
oscillator.frequency.cancelScheduledValues(0);
206+
oscillator.frequency.setTargetAtTime( frequencyFromNoteNumber(noteNumber), 0, portamento );
207+
envelope.gain.cancelScheduledValues(0);
208+
envelope.gain.setTargetAtTime(1.0, 0, attack);
209+
}
210+
211+
function noteOff(noteNumber) {
212+
var position = activeNotes.indexOf(noteNumber);
213+
if (position!=-1) {
214+
activeNotes.splice(position,1);
215+
}
216+
if (activeNotes.length==0) { // shut off the envelope
217+
envelope.gain.cancelScheduledValues(0);
218+
envelope.gain.setTargetAtTime(0.0, 0, release );
219+
} else {
220+
oscillator.frequency.cancelScheduledValues(0);
221+
oscillator.frequency.setTargetAtTime( frequencyFromNoteNumber(activeNotes[activeNotes.length-1]), 0, portamento );
222+
}
223+
}
224+
```

0 commit comments

Comments
 (0)