0
# MIDI Output
1
2
MIDI Output functionality provides comprehensive capabilities for sending MIDI messages to instruments and devices. Output objects represent physical or virtual MIDI output ports, while OutputChannel objects provide channel-specific message sending.
3
4
## Capabilities
5
6
### Output Port Management
7
8
Access and manage MIDI output ports.
9
10
```javascript { .api }
11
class Output extends EventEmitter {
12
/**
13
* Array of 16 OutputChannel objects (channels 1-16)
14
*/
15
readonly channels: OutputChannel[];
16
17
/**
18
* Output port name as reported by the system
19
*/
20
readonly name: string;
21
22
/**
23
* Unique identifier for this output port
24
*/
25
readonly id: string;
26
27
/**
28
* Connection state: "closed", "open", or "pending"
29
*/
30
readonly connection: string;
31
32
/**
33
* Port state: "connected" or "disconnected"
34
*/
35
readonly state: string;
36
37
/**
38
* Device manufacturer name (if available)
39
*/
40
readonly manufacturer: string;
41
42
/**
43
* Port type (always "output")
44
*/
45
readonly type: string;
46
47
/**
48
* Octave offset for this output (-10 to 10)
49
*/
50
readonly octaveOffset: number;
51
}
52
```
53
54
### Core Message Sending
55
56
Send raw MIDI messages and system exclusive data.
57
58
```javascript { .api }
59
/**
60
* Send raw MIDI message
61
* @param message - MIDI message as array or Uint8Array
62
* @param options - Send options
63
* @param options.time - When to send (0 = now, or timestamp)
64
* @param legacy - Legacy timestamp parameter (deprecated)
65
* @returns Output instance for chaining
66
*/
67
send(message: number[] | Uint8Array, options?: {time?: number}, legacy?: number): Output;
68
69
/**
70
* Send system exclusive message
71
* @param identification - Manufacturer ID bytes
72
* @param data - SysEx data bytes
73
* @param options - Send options
74
* @returns Output instance for chaining
75
*/
76
sendSysex(identification: number[], data?: number[], options?: {time?: number}): Output;
77
78
/**
79
* Clear all pending messages and stop all notes
80
* @returns Output instance for chaining
81
*/
82
clear(): Output;
83
```
84
85
**Usage Examples:**
86
87
```javascript
88
import { WebMidi } from "webmidi";
89
90
await WebMidi.enable({ sysex: true });
91
const output = WebMidi.outputs[0];
92
93
// Send raw MIDI message (note on, channel 1, C4, velocity 100)
94
output.send([0x90, 60, 100]);
95
96
// Send with timing
97
output.send([0x90, 60, 100], { time: WebMidi.time + 1000 });
98
99
// Send SysEx message
100
output.sendSysex([0x41], [0x10, 0x16, 0x12]); // Roland message
101
102
// Clear all messages
103
output.clear();
104
```
105
106
### System Real-Time Messages
107
108
Send MIDI system real-time messages for synchronization.
109
110
```javascript { .api }
111
/**
112
* Send MIDI clock pulse
113
* @param options - Send options
114
* @returns Output instance for chaining
115
*/
116
sendClock(options?: {time?: number}): Output;
117
118
/**
119
* Send start message
120
* @param options - Send options
121
* @returns Output instance for chaining
122
*/
123
sendStart(options?: {time?: number}): Output;
124
125
/**
126
* Send continue message
127
* @param options - Send options
128
* @returns Output instance for chaining
129
*/
130
sendContinue(options?: {time?: number}): Output;
131
132
/**
133
* Send stop message
134
* @param options - Send options
135
* @returns Output instance for chaining
136
*/
137
sendStop(options?: {time?: number}): Output;
138
139
/**
140
* Send active sensing message
141
* @param options - Send options
142
* @returns Output instance for chaining
143
*/
144
sendActiveSensing(options?: {time?: number}): Output;
145
146
/**
147
* Send system reset message
148
* @param options - Send options
149
* @returns Output instance for chaining
150
*/
151
sendReset(options?: {time?: number}): Output;
152
```
153
154
### System Common Messages
155
156
Send system common messages for timing and tuning.
157
158
```javascript { .api }
159
/**
160
* Send timecode quarter frame
161
* @param value - Quarter frame value (0-127)
162
* @param options - Send options
163
* @returns Output instance for chaining
164
*/
165
sendTimecodeQuarterFrame(value: number, options?: {time?: number}): Output;
166
167
/**
168
* Send song position pointer
169
* @param value - Song position in beats (0-16383)
170
* @param options - Send options
171
* @returns Output instance for chaining
172
*/
173
sendSongPosition(value?: number, options?: {time?: number}): Output;
174
175
/**
176
* Send song select
177
* @param value - Song number (0-127)
178
* @param options - Send options
179
* @returns Output instance for chaining
180
*/
181
sendSongSelect(value?: number, options?: {time?: number}): Output;
182
183
/**
184
* Send tune request
185
* @param options - Send options
186
* @returns Output instance for chaining
187
*/
188
sendTuneRequest(options?: {time?: number}): Output;
189
```
190
191
### Channel Messages (All Channels)
192
193
Send channel messages to all channels or specific channels.
194
195
```javascript { .api }
196
/**
197
* Send control change message
198
* @param controller - Controller number (0-127) or name
199
* @param value - Controller value (0-1 or 0-127)
200
* @param options - Send options
201
* @param options.channels - Target channels (default: "all")
202
* @param options.time - When to send
203
* @param legacy - Legacy options (deprecated)
204
* @returns Output instance for chaining
205
*/
206
sendControlChange(
207
controller: number | string,
208
value: number,
209
options?: {channels?: number | number[] | "all"; time?: number},
210
legacy?: object
211
): Output;
212
213
/**
214
* Send pitch bend message
215
* @param value - Pitch bend value (-1 to 1 or 0-16383)
216
* @param options - Send options
217
* @param options.channels - Target channels (default: "all")
218
* @param options.time - When to send
219
* @param legacy - Legacy options (deprecated)
220
* @returns Output instance for chaining
221
*/
222
sendPitchBend(
223
value?: number,
224
options?: {channels?: number | number[] | "all"; time?: number},
225
legacy?: object
226
): Output;
227
228
/**
229
* Send program change message
230
* @param program - Program number (0-127 or 1-128)
231
* @param options - Send options
232
* @param options.channels - Target channels (default: "all")
233
* @param options.time - When to send
234
* @param legacy - Legacy options (deprecated)
235
* @returns Output instance for chaining
236
*/
237
sendProgramChange(
238
program?: number,
239
options?: {channels?: number | number[] | "all"; time?: number},
240
legacy?: object
241
): Output;
242
243
/**
244
* Send channel aftertouch message
245
* @param pressure - Pressure value (0-1 or 0-127)
246
* @param options - Send options
247
* @param options.channels - Target channels (default: "all")
248
* @param options.time - When to send
249
* @param legacy - Legacy options (deprecated)
250
* @returns Output instance for chaining
251
*/
252
sendChannelAftertouch(
253
pressure: number,
254
options?: {channels?: number | number[] | "all"; time?: number},
255
legacy?: object
256
): Output;
257
258
/**
259
* Send key aftertouch message
260
* @param note - Note to apply pressure to
261
* @param pressure - Pressure value (0-1 or 0-127)
262
* @param options - Send options
263
* @param options.channels - Target channels (default: "all")
264
* @param options.time - When to send
265
* @returns Output instance for chaining
266
*/
267
sendKeyAftertouch(
268
note: string | number | Note,
269
pressure: number,
270
options?: {channels?: number | number[] | "all"; time?: number}
271
): Output;
272
```
273
274
### Registered Parameter Numbers (RPN)
275
276
Send and manage RPN messages for extended control.
277
278
```javascript { .api }
279
/**
280
* Send RPN value
281
* @param parameter - RPN parameter name or number
282
* @param data - Parameter data
283
* @param options - Send options
284
* @param options.channels - Target channels (default: "all")
285
* @param options.time - When to send
286
* @returns Output instance for chaining
287
*/
288
sendRpnValue(
289
parameter: string | number,
290
data: number | number[],
291
options?: {channels?: number | number[] | "all"; time?: number}
292
): Output;
293
294
/**
295
* Set registered parameter
296
* @param parameter - RPN parameter name or number
297
* @param data - Parameter data
298
* @param channel - Target channels (default: "all")
299
* @param options - Send options
300
* @returns Output instance for chaining
301
*/
302
setRegisteredParameter(
303
parameter: string | number,
304
data?: number[],
305
channel?: number | number[] | "all",
306
options?: {time?: number}
307
): Output;
308
309
/**
310
* Send pitch bend range RPN
311
* @param semitones - Semitone range (0-127)
312
* @param cents - Cent range (0-127)
313
* @param options - Send options
314
* @returns Output instance for chaining
315
*/
316
sendPitchBendRange(
317
semitones?: number,
318
cents?: number,
319
options?: {channels?: number | number[] | "all"; time?: number}
320
): Output;
321
322
/**
323
* Set pitch bend range
324
* @param semitones - Semitone range (0-127)
325
* @param cents - Cent range (0-127)
326
* @param channel - Target channels (default: "all")
327
* @param options - Send options
328
* @returns Output instance for chaining
329
*/
330
setPitchBendRange(
331
semitones?: number,
332
cents?: number,
333
channel?: number | number[] | "all",
334
options?: {time?: number}
335
): Output;
336
```
337
338
### OutputChannel
339
340
Channel-specific output for targeted MIDI communication.
341
342
```javascript { .api }
343
class OutputChannel extends EventEmitter {
344
/**
345
* Channel number (1-16)
346
*/
347
readonly number: number;
348
349
/**
350
* Parent Output object
351
*/
352
readonly output: Output;
353
354
/**
355
* Octave offset for this channel
356
*/
357
readonly octaveOffset: number;
358
}
359
```
360
361
### Channel-Specific Note Control
362
363
```javascript { .api }
364
/**
365
* Play note(s) on this channel
366
* @param note - Note(s) to play
367
* @param options - Play options
368
* @param options.velocity - Note velocity (0-1, default: 0.5)
369
* @param options.duration - Note duration in ms
370
* @param options.time - When to play
371
* @param options.release - Release velocity (0-1)
372
* @returns OutputChannel instance for chaining
373
*/
374
playNote(note: string | number | Note | Array<string | number | Note>, options?: {
375
velocity?: number;
376
duration?: number;
377
time?: number;
378
release?: number;
379
}): OutputChannel;
380
381
/**
382
* Send note on message
383
* @param note - Note(s) to turn on
384
* @param options - Note on options
385
* @param options.velocity - Note velocity (0-1, default: 0.5)
386
* @param options.time - When to send
387
* @returns OutputChannel instance for chaining
388
*/
389
sendNoteOn(note: string | number | Note | Array<string | number | Note>, options?: {
390
velocity?: number;
391
time?: number;
392
}): OutputChannel;
393
394
/**
395
* Send note off message
396
* @param note - Note(s) to turn off
397
* @param options - Note off options
398
* @param options.velocity - Release velocity (0-1, default: 0.5)
399
* @param options.time - When to send
400
* @returns OutputChannel instance for chaining
401
*/
402
sendNoteOff(note: string | number | Note | Array<string | number | Note>, options?: {
403
velocity?: number;
404
time?: number;
405
}): OutputChannel;
406
407
/**
408
* Stop note(s) (alias for sendNoteOff)
409
* @param note - Note(s) to stop
410
* @param options - Stop options
411
* @returns OutputChannel instance for chaining
412
*/
413
stopNote(note: string | number | Note | Array<string | number | Note>, options?: {
414
velocity?: number;
415
time?: number;
416
}): OutputChannel;
417
```
418
419
**Usage Examples:**
420
421
```javascript
422
const output = WebMidi.outputs[0];
423
const channel1 = output.channels[0]; // Channel 1
424
425
// Play a single note
426
channel1.playNote("C4");
427
428
// Play with options
429
channel1.playNote("C4", {
430
velocity: 0.8,
431
duration: 2000, // 2 seconds
432
time: WebMidi.time + 500 // Play in 500ms
433
});
434
435
// Play multiple notes (chord)
436
channel1.playNote(["C4", "E4", "G4"], { velocity: 0.7 });
437
438
// Send note on/off manually
439
channel1.sendNoteOn("C4", { velocity: 0.8 });
440
setTimeout(() => {
441
channel1.sendNoteOff("C4");
442
}, 1000);
443
```
444
445
### Channel-Specific Control Messages
446
447
```javascript { .api }
448
/**
449
* Send control change on this channel
450
* @param controller - Controller number (0-127) or name
451
* @param value - Controller value (0-1 or 0-127)
452
* @param options - Send options
453
* @returns OutputChannel instance for chaining
454
*/
455
sendControlChange(controller: number | string, value: number, options?: {time?: number}): OutputChannel;
456
457
/**
458
* Send pitch bend on this channel
459
* @param value - Pitch bend value (-1 to 1 or 0-16383)
460
* @param options - Send options
461
* @returns OutputChannel instance for chaining
462
*/
463
sendPitchBend(value?: number, options?: {time?: number}): OutputChannel;
464
465
/**
466
* Send program change on this channel
467
* @param program - Program number (0-127 or 1-128)
468
* @param options - Send options
469
* @returns OutputChannel instance for chaining
470
*/
471
sendProgramChange(program: number, options?: {time?: number}): OutputChannel;
472
473
/**
474
* Send channel aftertouch on this channel
475
* @param pressure - Pressure value (0-1 or 0-127)
476
* @param options - Send options
477
* @returns OutputChannel instance for chaining
478
*/
479
sendChannelAftertouch(pressure: number, options?: {time?: number}): OutputChannel;
480
481
/**
482
* Send key aftertouch on this channel
483
* @param target - Note to apply pressure to
484
* @param pressure - Pressure value (0-1 or 0-127)
485
* @param options - Send options
486
* @returns OutputChannel instance for chaining
487
*/
488
sendKeyAftertouch(target: string | number | Note, pressure: number, options?: {time?: number}): OutputChannel;
489
```
490
491
### Advanced Channel Parameters
492
493
```javascript { .api }
494
/**
495
* Send RPN value on this channel
496
* @param rpn - RPN parameter name or number
497
* @param data - Parameter data
498
* @param options - Send options
499
* @returns OutputChannel instance for chaining
500
*/
501
sendRpnValue(rpn: string | number, data: number | number[], options?: {time?: number}): OutputChannel;
502
503
/**
504
* Send NRPN value on this channel
505
* @param nrpn - NRPN parameter number
506
* @param data - Parameter data
507
* @param options - Send options
508
* @returns OutputChannel instance for chaining
509
*/
510
sendNrpnValue(nrpn: number, data: number | number[], options?: {time?: number}): OutputChannel;
511
512
/**
513
* Send pitch bend range on this channel
514
* @param semitones - Semitone range
515
* @param cents - Cent range
516
* @param options - Send options
517
* @returns OutputChannel instance for chaining
518
*/
519
sendPitchBendRange(semitones: number, cents: number, options?: {time?: number}): OutputChannel;
520
521
/**
522
* Send master tuning on this channel
523
* @param value - Tuning value in cents
524
* @param options - Send options
525
* @returns OutputChannel instance for chaining
526
*/
527
sendMasterTuning(value: number, options?: {time?: number}): OutputChannel;
528
529
/**
530
* Send modulation range on this channel
531
* @param semitones - Semitone range
532
* @param cents - Cent range
533
* @param options - Send options
534
* @returns OutputChannel instance for chaining
535
*/
536
sendModulationRange(semitones: number, cents: number, options?: {time?: number}): OutputChannel;
537
```
538
539
### Channel Mode Messages
540
541
```javascript { .api }
542
/**
543
* Send channel mode message
544
* @param command - Mode command name or number
545
* @param value - Command value (default: 0)
546
* @param options - Send options
547
* @returns OutputChannel instance for chaining
548
*/
549
sendChannelMode(command: string | number, value?: number, options?: {time?: number}): OutputChannel;
550
551
/**
552
* Send omni mode message
553
* @param state - Omni state (true/false or "on"/"off")
554
* @param options - Send options
555
* @returns OutputChannel instance for chaining
556
*/
557
sendOmniMode(state: boolean | "on" | "off", options?: {time?: number}): OutputChannel;
558
559
/**
560
* Send all notes off message
561
* @param options - Send options
562
* @returns OutputChannel instance for chaining
563
*/
564
sendAllNotesOff(options?: {time?: number}): OutputChannel;
565
566
/**
567
* Send all sound off message (emergency stop)
568
* @param options - Send options
569
* @returns OutputChannel instance for chaining
570
*/
571
sendAllSoundOff(options?: {time?: number}): OutputChannel;
572
573
/**
574
* Send local control message
575
* @param state - Local control state (true/false or "on"/"off")
576
* @param options - Send options
577
* @returns OutputChannel instance for chaining
578
*/
579
sendLocalControl(state: boolean | "on" | "off", options?: {time?: number}): OutputChannel;
580
581
/**
582
* Send mono mode message
583
* @param channels - Number of channels for mono mode (1-16, default: 1)
584
* @param options - Send options
585
* @returns OutputChannel instance for chaining
586
*/
587
sendMonoMode(channels?: number, options?: {time?: number}): OutputChannel;
588
589
/**
590
* Send reset all controllers message
591
* @param options - Send options
592
* @returns OutputChannel instance for chaining
593
*/
594
sendResetAllControllers(options?: {time?: number}): OutputChannel;
595
596
/**
597
* Destroy the output channel (cleanup)
598
*/
599
destroy(): void;
600
```
601
602
## Usage Examples
603
604
### Basic Output Usage
605
606
```javascript
607
import { WebMidi } from "webmidi";
608
609
await WebMidi.enable();
610
const output = WebMidi.getOutputByName("My Synthesizer");
611
612
// Play a simple melody
613
const melody = ["C4", "D4", "E4", "F4", "G4"];
614
melody.forEach((note, index) => {
615
output.channels[0].playNote(note, {
616
time: WebMidi.time + (index * 500),
617
duration: 400
618
});
619
});
620
621
// Send control changes
622
output.sendControlChange("volume", 100, { channels: [1, 2, 3] });
623
output.sendControlChange(64, 127); // Sustain pedal on all channels
624
625
// Change programs
626
output.sendProgramChange(1, { channels: 1 }); // Piano on channel 1
627
output.sendProgramChange(25, { channels: 10 }); // Steel guitar on channel 10
628
```
629
630
### Advanced Timing and Scheduling
631
632
```javascript
633
const startTime = WebMidi.time + 1000; // Start in 1 second
634
635
// Schedule a chord progression
636
const chords = [
637
["C4", "E4", "G4"], // C major
638
["F4", "A4", "C5"], // F major
639
["G4", "B4", "D5"], // G major
640
["C4", "E4", "G4"] // C major
641
];
642
643
chords.forEach((chord, index) => {
644
chord.forEach(note => {
645
output.channels[0].playNote(note, {
646
time: startTime + (index * 2000), // 2 seconds per chord
647
duration: 1800,
648
velocity: 0.7
649
});
650
});
651
});
652
```
653
654
## Types
655
656
```javascript { .api }
657
interface SendOptions {
658
time?: number;
659
}
660
661
interface NoteOptions {
662
velocity?: number;
663
duration?: number;
664
time?: number;
665
release?: number;
666
}
667
668
interface ChannelOptions {
669
channels?: number | number[] | "all";
670
time?: number;
671
}
672
```