@@ -7,3 +7,187 @@ This package adds midi functionality to strudel Patterns.
77``` sh
88npm i @strudel/midi --save
99```
10+
11+ ## Available Controls
12+
13+ The following MIDI controls are available:
14+
15+ OUTPUT:
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+
36+ INPUT:
37+
38+ - ` midin ` - Opens a MIDI input port to receive MIDI control change messages.
39+
40+ Additional controls can be mapped using the mapping object passed to ` .midi() ` :
41+
42+ ## Examples
43+
44+ ### midi(outputName?, options?)
45+
46+ Either connect a midi device or use the IAC Driver (Mac) or Midi Through Port (Linux) for internal midi messages.
47+ If 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+
53+ In 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+
57+ The ` .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+
84+ Selects 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+
93+ Selects 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+
107+ In the above snippet, ` ccn ` is set to 74, which is the filter cutoff for many synths. ` ccv ` is controlled by a saw pattern.
108+ Having everything in one pattern, the ` ccv ` pattern will be aligned to the note pattern, because the structure comes from the left by default.
109+ But 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.
119+ Program change values should be numbers between 0 and 127.
120+
121+ ``` javascript
122+ // Play notes while changing programs
123+ note (" c3 e3 g3" ).progNum (" <0 1 2>" ).midi ()
124+ ```
125+
126+ Program change messages are useful for switching between different instrument sounds or presets during a performance.
127+ The 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.
132+ sysEx messages are device-specific commands that allow deeper control over synthesizer parameters.
133+ The value should be an array of numbers between 0-255 representing the SysEx data bytes.
134+
135+ ``` javascript
136+ // Send a simple SysEx message
137+ let id = 0x43 ; // Yamaha
138+ // let id = "0x00:0x20:0x32"; //Behringer ID can be an array of numbers
139+ let 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+
144+ The exact format of SysEx messages depends on your MIDI device's specification.
145+ Consult 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+
163+ It 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.
173+ stack (
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
185+ stack (
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+ ```
0 commit comments