jevstrudel.git / packages / midi / README.md
README.mdpreviewREADME.mdsource193 lines · 6.5 KB · raw
1# @strudel/midi
2
3This package adds midi functionality to strudel Patterns.
4
5## Install
6
7```sh
8npm i @strudel/midi --save
9```
10
11## Available Controls
12
13The following MIDI controls are available:
14
15OUTPUT:
16
17- `midi` - opens a midi output device.
18- `note` - Sends MIDI note messages. Can accept note names (e.g. "c4") or MIDI note numbers (0-127)
19- `midichan` - Sets the MIDI channel (1-16, defaults to 1)
20- `velocity` - Sets note velocity (0-1, defaults to 0.9)
21- `gain` - Modifies velocity by multiplying with it (0-1, defaults to 1)
22- `control` - Sets MIDI control change messages
23- `ccn` - Sets MIDI CC controller number (0-127)
24- `ccv` - Sets MIDI CC value (0-1)
25- `progNum` - Sends MIDI program change messages (0-127)
26- `sysex` - Sends MIDI System Exclusive messages (id: number 0-127 or array of bytes 0-127, data: array of bytes 0-127)
27- `sysexid` - Sets MIDI System Exclusive ID (number 0-127 or array of bytes 0-127)
28- `sysexdata` - Sets MIDI System Exclusive data (array of bytes 0-127)
29- `midibend` - Sets MIDI pitch bend (-1 - 1)
30- `miditouch` - Sets MIDI key after touch (0-1)
31- `midicmd` - Sends MIDI system real-time messages to control timing and transport on MIDI devices.
32- `nrpnn` - Sets MIDI NRPN non-registered parameter number (array of bytes 0-127)
33- `nrpv` - Sets MIDI NRPN non-registered parameter value (0-127)
34
35
36INPUT:
37
38- `midin` - Opens a MIDI input port to receive MIDI control change messages.
39
40Additional controls can be mapped using the mapping object passed to `.midi()`:
41
42## Examples
43
44### midi(outputName?, options?)
45
46Either connect a midi device or use the IAC Driver (Mac) or Midi Through Port (Linux) for internal midi messages.
47If no outputName is given, it uses the first midi output it finds.
48
49```javascript
50$: chord("<C^7 A7 Dm7 G7>").voicing().midi('IAC Driver')
51```
52
53In the console, you will see a log of the available MIDI devices as soon as you run the code, e.g. `Midi connected! Using "Midi Through Port-0".`
54
55### Options
56
57The `.midi()` function accepts an options object with the following properties:
58
59```javascript
60$: note("c a f e").midi('IAC Driver', { isController: true, midimap: 'default'})
61```
62
63<details>
64<summary>Available Options</summary>
65
66| Option | Type | Default | Description |
67|--------|------|---------|-------------|
68| isController | boolean | false | When true, disables sending note messages. Useful for MIDI controllers |
69| latencyMs | number | 34 | Latency in milliseconds to align MIDI with audio engine |
70| noteOffsetMs | number | 10 | Offset in milliseconds for note-off messages to prevent glitching |
71| midichannel | number | 1 | Default MIDI channel (1-16) |
72| velocity | number | 0.9 | Default note velocity (0-1) |
73| gain | number | 1 | Default gain multiplier for velocity (0-1) |
74| midimap | string | 'default' | Name of MIDI mapping to use for control changes |
75| midiport | string/number | - | MIDI device name or index |
76
77</details>
78
79
80
81
82### midiport(outputName)
83
84Selects the MIDI output device to use, pattern can be used to switch between devices.
85
86```javascript
87$: midiport('IAC Driver')
88$: note("c a f e").midiport("<0 1 2 3>").midi()
89```
90
91### midichan(number)
92
93Selects the MIDI channel to use. If not used, `.midi` will use channel 1 by default.
94
95### control, ccn && ccv
96
97`control` sends MIDI control change messages to your MIDI device.
98
99- `ccn` sets the cc number. Depends on your synths midi mapping
100- `ccv` sets the cc value. normalized from 0 to 1.
101
102```javascript
103$: note("c a f e").control([74, sine.slow(4)]).midi()
104$: note("c a f e").ccn(74).ccv(sine.slow(4)).midi()
105```
106
107In the above snippet, `ccn` is set to 74, which is the filter cutoff for many synths. `ccv` is controlled by a saw pattern.
108Having everything in one pattern, the `ccv` pattern will be aligned to the note pattern, because the structure comes from the left by default.
109But you can also control cc messages separately like this:
110
111```javascript
112$: note("c a f e").midi()
113$: ccv(sine.segment(16).slow(4)).ccn(74).midi()
114```
115
116### progNum (Program Change)
117
118`progNum` control sends MIDI program change messages to switch between different presets/patches on your MIDI device.
119Program change values should be numbers between 0 and 127.
120
121```javascript
122// Play notes while changing programs
123note("c3 e3 g3").progNum("<0 1 2>").midi()
124```
125
126Program change messages are useful for switching between different instrument sounds or presets during a performance. 
127The exact sound that each program number maps to depends on your MIDI device's configuration.
128
129## sysex,  sysexid && sysexdata (System Exclusive Message)
130
131`sysex`, `sysexid` and `sysexdata` control sends MIDI System Exclusive (SysEx) messages to your MIDI device. 
132sysEx messages are device-specific commands that allow deeper control over synthesizer parameters. 
133The value should be an array of numbers between 0-255 representing the SysEx data bytes.
134
135```javascript
136// Send a simple SysEx message
137let id = 0x43; //Yamaha
138//let id = "0x00:0x20:0x32"; //Behringer ID can be an array of numbers
139let data = "0x79:0x09:0x11:0x0A:0x00:0x00"; // Set NSX-39 voice to say "Aa"
140$: note("c d e f e d c").sysex(id, data).midi();
141$: note("c d e f e d c").sysexid(id).sysexdata(data).midi();
142```
143
144The exact format of SysEx messages depends on your MIDI device's specification.
145Consult your device's MIDI implementation guide for details on supported SysEx messages.
146
147### midibend && miditouch
148
149`midibend` sets MIDI pitch bend (-1 - 1)
150`miditouch` sets MIDI key after touch (0-1)
151
152```javascript
153
154$: note("c d e f e d c").midibend(sine.slow(4).range(-0.4,0.4)).midi();
155$: note("c d e f e d c").miditouch(sine.slow(4).range(0,1)).midi();
156
157```
158
159### midicmd
160
161`midicmd` sends MIDI system real-time messages to control timing and transport on MIDI devices.
162
163It supports the following commands:
164
165- `clock`/`midiClock` - Sends MIDI timing clock messages
166- `start` - Sends MIDI start message
167- `stop` - Sends MIDI stop message
168- `continue` - Sends MIDI continue message
169
170```javascript
171// You can control the clock with a pattern and ensure it starts in sync when the repl begins.
172// Note: It might act unexpectedly if MIDI isn't set up initially.
173stack(
174  midicmd("clock*48,<start stop>/2").midi('IAC Driver') 
175)
176```
177
178`midicmd` also supports sending control change, program change and sysex messages.
179
180- `cc` - sends MIDI control change messages.
181- `progNum` - sends MIDI program change messages.
182- `sysex` - sends MIDI system exclusive messages.
183
184```javascript
185stack(
186  // "cc:ccn:ccv"
187  midicmd("cc:74:1").midi('IAC Driver'),
188  // "progNum:progNum"
189  midicmd("progNum:1").midi('IAC Driver'),
190  // "sysex:[sysexid]:[sysexdata]"
191  midicmd("sysex:[0x43]:[0x79:0x09:0x11:0x0A:0x00:0x00]").midi('IAC Driver')
192)
193```