# noon-io

> Easy io for the Web MIDI API

Latest version **0.5.10** (published 2024-03-04) · apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install noon-io
pnpm add noon-io
yarn add noon-io
bun add noon-io
```

## Health

**Score 30/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.5.10 |
| Published | 2024-03-04 |
| First published | 2022-02-26 |
| Weekly downloads | 0 |
| License | apache-2.0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 4 |
| Unpacked size | 87 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 3 |
| Author | Antoine Cordier |
| Maintainers | a-cordier |
| Keywords | web, midi, music |

## Links

- npm: https://www.npmjs.com/package/noon-io
- Repository: https://github.com/a-cordier/noon-io
- Homepage: https://github.com/a-cordier/noon-io#readme
- Issues: https://github.com/a-cordier/noon-io/issues
- npm.io page: https://npm.io/package/noon-io

## Dependencies (4)

- [rxjs](https://npm.io/package/rxjs.md) ^7.8.1
- [tscpaths](https://npm.io/package/tscpaths.md) ^0.0.9
- [@types/node](https://npm.io/package/@types/node.md) ^18.16.3
- [tsconfig-paths](https://npm.io/package/tsconfig-paths.md) ^4.2.0

## Alternatives

- [@opentelemetry/exporter-zipkin](https://npm.io/package/@opentelemetry/exporter-zipkin.md) — 14.8M weekly downloads
- [pusher-js](https://npm.io/package/pusher-js.md) — 2.0M weekly downloads
- [browserify](https://npm.io/package/browserify.md) — 1.7M weekly downloads
- [sqs-consumer](https://npm.io/package/sqs-consumer.md) — 1.7M weekly downloads
- [@sanity/eventsource](https://npm.io/package/@sanity/eventsource.md) — 930.8K weekly downloads

## Recent versions

- 0.5.10 (latest) — 2024-03-04
- 0.5.9 — 2023-05-16
- 0.5.8 — 2023-05-07
- 0.5.7 — 2023-05-07
- 0.5.6 — 2023-05-04
- 0.5.5 — 2023-05-03
- 0.5.4 — 2023-05-03
- 0.5.3 — 2023-05-03
- 0.5.2 — 2023-05-03
- 0.5.1 — 2023-05-03
- 0.5.0 — 2023-05-03
- 0.4.0 — 2023-05-03
- 0.3.0 — 2023-05-02
- 0.2.0 — 2023-05-02
- 0.1.3 — 2023-05-02
- … 32 more at https://npm.io/package/noon-io/versions

## README

# 🎹 noon-io

![tests](https://github.com/a-cordier/noon-io/actions/workflows/tests.yaml/badge.svg)
![release](https://github.com/a-cordier/noon-io/actions/workflows/release.yaml/badge.svg)
![doc](https://github.com/a-cordier/noon-io/actions/workflows/doc.yaml/badge.svg)

Easy io for the [Web MIDI API](https://www.w3.org/TR/webmidi/)

## 🚨 Disclaimer

Development has just started and until v1.0.0 has been released, noon-io should be considered unstable.

# 🗒️ API Documentation

A more detailed documentation of noon-io can be found [here](https://a-cordier.github.io/noon-io).

# 🚀 Getting started

## 📦 Install

```bash
npm i noon-io
```

## 📤 Send MIDI messages

Send a A4 `NOTE ON` message on all available MIDI outputs

```typescript
import * as MIDI from 'noon-io';

// Gain access to the Web MIDI API
const midiAccess = await navigator.requestMIDIAccess();

// Send a Note On message over all available outputs on channel 2
for (const output of midiAccess.outputs.values()) {
    const noteOnMessage = {
        status: MIDI.Status.NOTE_ON,
        channel: 2,
        data: {
            value: 69, // A4
            velocity: 127
        }
    };
    output.send(MIDI.write(noteOnMessage));
}
```

## 🔨 Using channel message factory functions

For one dedicated channel, noon-io offers a more concise way of writing messages using factory functions.

```typescript
// send a CC of 80 for control 71
output.send(MIDI.channel(2).controlChange(71, 80));
// send a A4 note on message with a velocity of 120
output.send(MIDI.channel(2).noteOn(69, 120));
// send the subsequent note off message for our A4 note
output.send(MIDI.channel(2).noteOff(69));
```

For more information about noon-io factories, you can checkout this [documentation](https://a-cordier.github.io/noon-io/docs/interfaces/ChannelMessageFactory.html)

## 📥 Read MIDI messages

```typescript
import * as MIDI from 'noon-io';

// Gain access to the Web MIDI API
const midiAccess = await navigator.requestMIDIAccess();

// Bind MIDI reader to all midi inputs
for (const input of midiAccess.inputs.values()) {
    input.onmidimessage = MIDI.read;
}
```

## 🎨 Decorating MIDI messages

The read function can be instantiated through the `reader` factory which takes an optional configuration object. This object allow to define one decorator function per MIDI status,
in order to populate the `meta` property of the message with application specific data,
in order to implement custom logic when subscribing to the message.

```typescript
// example: read current UI state to check if MIDI learning is enabled
input.onmidimessage = MIDI.reader({
    decorators: {
        [MIDI.Status.CONTROL_CHANGE](message) {
            return {
                isMidiLearning: isMidiLearning() 
            };
        }
    },
});
```

# ⏳ Subscribing to the messages stream

Once read, messages are exposed through the `Rx` Subject.

```typescript
import * as MIDI from 'noon-io';

MIDI.Rx.subscribe(message => {
    console.log(message.meta); // log the meta object populated by the custom decorator function
});
```

# ⏳ Filtering messages

In addition to the message stream, noon-io provides a convenient `observe` function,
which will return a observable of MIDI messages matching the given MIDI status and an optional MIDI chanel.

```typescript
import * as MIDI from 'noon-io';

MIDI.observe(MIDI.Status.CONTROL_CHANGE, 1)
    .subscribe(message => {
        // handle control change message for channel 1
    });
```

## ⚗️ Bank Select / Program Change

Sending a bank select followed by a program change can be achieved by sending two consecutive control change messages before 
sending the actual program change. 

(The following has been tested on a Dave Smith Instruments Mopho device)

```typescript
import * as MIDI from 'noon-io';
/*
 * Start Bank Select message
 * Selects banks 2 (bank 1 is 0) for channel 2
 */
output.send(
    MIDI.writeMidiMessage({
        status: MIDI.Status.CONTROL_CHANGE,
        channel: 2,
        data: {
            control: 0, // bank select MSB (always 0)
            value: 1, // MSB multiplier
        }
    })
);

output.send(
    MIDI.writeMidiMessage({
        status: MIDI.Status.CONTROL_CHANGE,
        channel: 2,
        data: {
            control: 0, // bank select LSB (always 32)
            value: 1, // LSB multiplier
        }
    })
); // Ends bank select message

/*
 * Now that we have selected bank 2,
 * let's select a random program
 */
output.send(
    MIDI.writeMidiMessage({
        status: MIDI.Status.PROGRAM_CHANGE,
        channel: 2,
        data: {
            value: Math.ceil(Math.random() * 127),
        }
    })
);

```

Or using the `bankSelectMSB` and `bankSelectLSB` factories provided by noon-io

```typescript
// Select bank 1
output.send(MIDI.channel(2).bankSelectMSB(0));
output.send(MIDI.channel(2).bankSelectLSB(0));
// Select program 109 from bank 1
output.send(MIDI.channel(2).programChange(Math.ceil(Math.random() * 127)));
```

# 🚧 Supported Messages

⚠️ Some of the following MIDI messages may not have been tested on a MIDI port (see the status section of the following tables)

## 🎶 Channel Messages

|Type|Reader|Writer|Status
|:--|:-:|:-:|:--|
|NOTE ON|✅|✅|Read and write have been tested on a MIDI port
|NOTE OFF|✅|✅|Read and write have been tested on a MIDI port
|PITCH BEND|✅|✅|Read and write have been tested on a MIDI port
|CONTROL CHANGE|✅|✅|Read and write have been tested on a MIDI port
|PROGRAM CHANGE|✅|✅|Read and write have been tested on a MIDI port
|POLYPHONIC AFTER TOUCH|✅|✅|Both read and write have not been tested
|CHANNEL AFTER TOUCH|✅|✅|Both read and write have not been tested

## 🎛️ System Messages

|Type|Reader|Writer|Status
|:--|:-:|:-:|:--|
|TIMING CLOCK|✅|✅|Only Read has been tester on a MIDI port
|START|✅|✅|Both read and write have not been tested
|STOP|✅|✅|Both read and write have not been tested
|CONTINUE|✅|✅|Both read and write have not been tested
|SYSTEM RESET|✅|✅|Both read and write have not been tested
|ACTIVE SENSING|✅|✅|Both read and write have not been tested
|SYSTEM EXCLUSIVE|✅|❌|Reader has not been tested, writer is not implemented
|MIDI TIME CODE|❌|❌|Not Implemented
|SONG POSITION|❌|❌|Not Implemented
|SONG SELECT|❌|❌|Not Implemented
|TUNE REQUEST|❌|❌|Not Implemented

---
_Source: https://npm.io/package/noon-io · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
