-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmidisynth.html
162 lines (132 loc) · 5.21 KB
/
midisynth.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<html>
http://www.w3.org/TR/webmidi/#examples-of-web-midi-api-usage-in-javascript
<hr />
Inputs<br />
<select size='5' id='midi_inputs'></select><br />
Output<br />
<select size='5' id='midi_outputs'></select><br />
<script>
var context=null; // the Web Audio "context" object
var midiAccess=null; // the MIDIAccess object.
var oscillator=null; // the single oscillator
var envelope=null; // the envelope for the single oscillator
var attack=0.0; // attack speed
var release=0.05; // release speed
var portamento=0.0; // portamento/glide speed
var activeNotes = []; // the stack of actively-pressed keys
window.addEventListener('load', function() {
// patch up prefixes
window.AudioContext=window.AudioContext||window.webkitAudioContext;
context = new AudioContext();
if (navigator.requestMIDIAccess)
navigator.requestMIDIAccess().then( onMIDIInit, onMIDIReject );
else
alert("No MIDI support present in your browser. You're gonna have a bad time.")
// set up the basic oscillator chain, muted to begin with.
oscillator = context.createOscillator();
oscillator.frequency.setValueAtTime(110, 0);
envelope = context.createGain();
oscillator.connect(envelope);
envelope.connect(context.destination);
envelope.gain.value = 0.0; // Mute the sound
oscillator.start(0); // Go ahead and start up the oscillator
} );
function onMIDIInit(midi) {
console.log('onMIDIInit(midi)',midi);
console.log('MIDI ready!');
midiAccess = midi;
var haveAtLeastOneDevice=false;
var inputs=midiAccess.inputs.values();
for ( var input = inputs.next(); input && !input.done; input = inputs.next()) {
console.log("input",input);
input.value.onmidimessage = MIDIMessageEventHandler;
haveAtLeastOneDevice = true;
var x = document.getElementById("midi_inputs");
var option = document.createElement("option");
option.value = input.value.id;
option.text = input.value.name;
x.add(option);
}
var outputs=midiAccess.outputs.values();
for ( var output = outputs.next(); output && !output.done; output = outputs.next()) {
console.log("output",output);
var x = document.getElementById("midi_outputs");
var option = document.createElement("option");
option.value = output.value.id;
option.text = output.value.name;
x.add(option);
}
if (!haveAtLeastOneDevice)
alert("No MIDI input devices present. You're gonna have a bad time.");
}
function onMIDIReject(err) {
alert("The MIDI system failed to start. You're gonna have a bad time.");
}
function onMIDIMessage( event ) {
var str = "MIDI message received at timestamp " + event.timestamp + "[" + event.data.length + " bytes]: ";
for (var i=0; i<event.data.length; i++) {
str += "0x" + event.data[i].toString(16) + " ";
}
console.log( str );
}
function startLoggingMIDIInput( midiAccess, indexOfPort ) {
midiAccess.inputs.forEach( function(entry) {entry.value.onmidimessage = onMIDIMessage;});
}
function sendMiddleC( mid, portID ) {
console.log('sendMiddleC(mid, portID)',mid, portID);
var noteOnMessage = [0x90, 60, 0x7f]; // note on, middle C, full velocity
var output = mid.outputs.get(portID);
output.send( noteOnMessage ); //omitting the timestamp means send immediately.
// note off
output.send( [0x80, 60, 0x40], window.performance.now() + 1000.0 ); // Inlined array creation- note off, middle C,
// release velocity = 64, timestamp = now + 1000ms.
}
function MIDIMessageEventHandler(event) {
console.log('MIDIMessageEventHandler(event)',event);
// Mask off the lower nibble (MIDI channel, which we don't care about)
switch (event.data[0] & 0xf0) {
case 0x90:
if (event.data[2]!=0) { // if velocity != 0, this is a note-on message
noteOn(event.data[1]);
return;
}
// if velocity == 0, fall thru: it's a note-off. MIDI's weird, y'all.
case 0x80:
noteOff(event.data[1]);
return;
}
}
function frequencyFromNoteNumber( note ) {
return 440 * Math.pow(2,(note-69)/12);
}
function noteOn(noteNumber) {
console.log('noteOn(noteNumber)',noteNumber);
activeNotes.push( noteNumber );
oscillator.frequency.cancelScheduledValues(0);
oscillator.frequency.setTargetAtTime( frequencyFromNoteNumber(noteNumber), 0, portamento );
envelope.gain.cancelScheduledValues(0);
envelope.gain.setTargetAtTime(1.0, 0, attack);
}
function noteOff(noteNumber) {
console.log('noteOff(noteNumber)',noteNumber);
var position = activeNotes.indexOf(noteNumber);
if (position!=-1) {
activeNotes.splice(position,1);
}
if (activeNotes.length==0) { // shut off the envelope
envelope.gain.cancelScheduledValues(0);
envelope.gain.setTargetAtTime(0.0, 0, release );
} else {
oscillator.frequency.cancelScheduledValues(0);
oscillator.frequency.setTargetAtTime( frequencyFromNoteNumber(activeNotes[activeNotes.length-1]), 0, portamento );
}
}
function listInputsAndOutputs( midi ) {
for (var input in midi.inputs) {
console.log( "Input",input.type,input.id,input.manufacturer,input.name,input.version);
}
for (var output in midi.outputs) {
console.log( "Output ",output.type,output.id,output.manufacturer,output.name,output.version);
}
}
</script>