or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

constants.mdindex.mdmessage-forwarding.mdmessage-processing.mdmidi-input.mdmidi-output.mdnote-processing.mdutilities.mdwebmidi-interface.md

midi-output.mddocs/

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

```