mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-14 07:08:30 +00:00
230 lines
8.5 KiB
Plaintext
230 lines
8.5 KiB
Plaintext
---
|
|
title: MIDI, OSC & MQTT
|
|
layout: ../../layouts/MainLayout.astro
|
|
---
|
|
|
|
import { MiniRepl } from '../../docs/MiniRepl';
|
|
import { JsDoc } from '../../docs/JsDoc';
|
|
|
|
# MIDI, OSC and MQTT
|
|
|
|
Normally, Strudel is used to pattern sound, using its own '[web audio](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)'-based synthesiser called [SuperDough](https://github.com/tidalcycles/strudel/tree/main/packages/superdough).
|
|
|
|
It is also possible to pattern other things with Strudel, such as software and hardware synthesisers with MIDI, other software using Open Sound Control/OSC (including the [SuperDirt](https://github.com/musikinformatik/SuperDirt/) synthesiser commonly used with Strudel's sibling [TidalCycles](https://tidalcycles.org/)), or the MQTT 'internet of things' protocol.
|
|
|
|
# MIDI
|
|
|
|
Strudel supports MIDI without any additional software (thanks to [webmidi](https://npmjs.com/package/webmidi)), just by adding methods to your pattern:
|
|
|
|
## midi(outputName?)
|
|
|
|
Either connect a midi device or use the IAC Driver (Mac) or Midi Through Port (Linux) for internal midi messages.
|
|
If no outputName is given, it uses the first midi output it finds.
|
|
|
|
<MiniRepl client:idle tune={`chord("<C^7 A7 Dm7 G7>").voicing().midi()`} />
|
|
|
|
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".`
|
|
|
|
## midichan(number)
|
|
|
|
Selects the MIDI channel to use. If not used, `.midi` will use channel 1 by default.
|
|
|
|
## midicmd(command)
|
|
|
|
`midicmd` sends MIDI system real-time messages to control timing and transport on MIDI devices.
|
|
|
|
It supports the following commands:
|
|
|
|
- `clock`/`midiClock` - Sends MIDI timing clock messages
|
|
- `start` - Sends MIDI start message
|
|
- `stop` - Sends MIDI stop message
|
|
- `continue` - Sends MIDI continue message
|
|
|
|
// You can control the clock with a pattern and ensure it starts in sync when the repl begins.
|
|
// Note: It might act unexpectedly if MIDI isn't set up initially.
|
|
|
|
<MiniRepl
|
|
client:idle
|
|
tune={`$:stack(
|
|
midicmd("clock*48,<start stop>/2").midi('IAC Driver')
|
|
)`}
|
|
/>
|
|
|
|
## control, ccn && ccv
|
|
|
|
- `control` sends MIDI control change messages to your MIDI device.
|
|
- `ccn` sets the cc number. Depends on your synths midi mapping
|
|
- `ccv` sets the cc value. normalized from 0 to 1.
|
|
|
|
<MiniRepl client:idle tune={`note("c a f e").control([74, sine.slow(4)]).midi()`} />
|
|
|
|
<MiniRepl client:idle tune={`note("c a f e").ccn(74).ccv(sine.slow(4)).midi()`} />
|
|
|
|
In the above snippet, `ccn` is set to 74, which is the filter cutoff for many synths. `ccv` is controlled by a saw pattern.
|
|
Having everything in one pattern, the `ccv` pattern will be aligned to the note pattern, because the structure comes from the left by default.
|
|
But you can also control cc messages separately like this:
|
|
|
|
<MiniRepl
|
|
client:idle
|
|
tune={`$: note("c a f e").midi()
|
|
$: ccv(sine.segment(16).slow(4)).ccn(74).midi()`}
|
|
/>
|
|
|
|
## progNum (Program Change)
|
|
|
|
`progNum` sends MIDI program change messages to switch between different presets/patches on your MIDI device.
|
|
Program change values should be numbers between 0 and 127.
|
|
|
|
<MiniRepl client:idle tune={`// Switch between programs 0 and 1 every cycle
|
|
progNum("<0 1>").midi()
|
|
|
|
// Play notes while changing programs
|
|
note("c3 e3 g3").progNum("<0 1 2>").midi()`} />
|
|
|
|
Program change messages are useful for switching between different instrument sounds or presets during a performance.
|
|
The exact sound that each program number maps to depends on your MIDI device's configuration.
|
|
|
|
## sysex, sysexid && sysexdata (System Exclusive Message)
|
|
|
|
`sysex` sends MIDI System Exclusive (SysEx) messages to your MIDI device.
|
|
ysEx messages are device-specific commands that allow deeper control over synthesizer parameters.
|
|
The value should be an array of numbers between 0-255 representing the SysEx data bytes.
|
|
|
|
<MiniRepl
|
|
client:idle
|
|
tune={`// Send a simple SysEx message
|
|
let id = 0x43; //Yamaha
|
|
//let id = "0x00:0x20:0x32"; //Behringer ID can be an array of numbers
|
|
let data = "0x79:0x09:0x11:0x0A:0x00:0x00"; // Set NSX-39 voice to say "Aa"
|
|
$: note("c d e f e d c").sysex(id, data).midi();
|
|
$: note("c d e f e d c").sysexid(id).sysexdata(data).midi();`}
|
|
/>
|
|
|
|
The exact format of SysEx messages depends on your MIDI device's specification.
|
|
Consult your device's MIDI implementation guide for details on supported SysEx messages.
|
|
|
|
## midibend && miditouch
|
|
|
|
`midibend` sets MIDI pitch bend (-1 - 1)
|
|
`miditouch` sets MIDI key after touch (0-1)
|
|
|
|
<MiniRepl client:idle tune={`note("c d e f e d c").midibend(sine.slow(4).range(-0.4,0.4)).midi()`} />
|
|
|
|
<MiniRepl client:idle tune={`note("c d e f e d c").miditouch(sine.slow(4).range(0,1)).midi()`} />
|
|
|
|
# OSC/SuperDirt/StrudelDirt
|
|
|
|
In TidalCycles, sound is usually generated using [SuperDirt](https://github.com/musikinformatik/SuperDirt/), which runs inside SuperCollider. Strudel also supports using SuperDirt, although it requires installing some additional software.
|
|
|
|
There is also [StrudelDirt](https://github.com/daslyfe/StrudelDirt) which is SuperDirt with some optimisations for working with Strudel. (A longer term aim is to merge these optimisations back into mainline SuperDirt)
|
|
|
|
## Prequisites
|
|
|
|
To get SuperDirt to work with Strudel, you need to
|
|
|
|
1. install SuperCollider + sc3 plugins, see [Tidal Docs](https://tidalcycles.org/docs/) (Install Tidal) for more info.
|
|
2. install SuperDirt, or the [StrudelDirt](https://github.com/daslyfe/StrudelDirt) fork which is optimised for use with Strudel
|
|
3. install [node.js](https://nodejs.org/en/)
|
|
4. download [Strudel Repo](https://github.com/tidalcycles/strudel/) (or git clone, if you have git installed)
|
|
5. run `pnpm i` in the strudel directory
|
|
6. run `pnpm run osc` to start the osc server, which forwards OSC messages from Strudel REPL to SuperCollider
|
|
|
|
Now you're all set!
|
|
|
|
## Usage
|
|
|
|
1. Start SuperCollider, either using SuperCollider IDE or by running `sclang` in a terminal
|
|
2. Open the [Strudel REPL](https://strudel.cc/#cygiYmQgc2QiKS5vc2MoKQ%3D%3D)
|
|
|
|
...or test it here:
|
|
|
|
<MiniRepl client:only="react" tune={`s("bd sd").osc()`} />
|
|
|
|
If you now hear sound, congratulations! If not, you can get help on the [#strudel channel in the TidalCycles discord](https://discord.com/invite/HGEdXmRkzT).
|
|
|
|
Note: if you have the 'Audio Engine Target' in settings set to 'OSC', you do not need to add .osc() to the end of your pattern.
|
|
|
|
### Pattern.osc
|
|
|
|
<JsDoc client:idle name="Pattern.osc" h={0} />
|
|
|
|
## SuperDirt Params
|
|
|
|
Please refer to [Tidal Docs](https://tidalcycles.org/) for more info.
|
|
|
|
<br />
|
|
|
|
But can we use Strudel [offline](/learn/pwa)?
|
|
|
|
# MQTT
|
|
|
|
MQTT is a lightweight network protocol, designed for 'internet of things' devices. For use with strudel, you will
|
|
need access to an MQTT server known as a 'broker' configured to accept secure 'websocket' connections. You could
|
|
run one yourself (e.g. by running [mosquitto](https://mosquitto.org/)), although getting an SSL certificate that
|
|
your web browser will trust might be a bit tricky for those without systems administration experience.
|
|
Alternatively, you can use [a public broker](https://www.hivemq.com/mqtt/public-mqtt-broker/).
|
|
|
|
Strudel does not yet support receiving messages over MQTT, only sending them.
|
|
|
|
## Usage
|
|
|
|
The following example shows how to send a pattern to an MQTT broker:
|
|
|
|
<MiniRepl
|
|
client:only="react"
|
|
tune={`"hello world"
|
|
.mqtt(undefined, // username (undefined for open/public servers)
|
|
undefined, // password
|
|
'/strudel-pattern', // mqtt 'topic'
|
|
'wss://mqtt.eclipseprojects.io:443/mqtt', // MQTT server address
|
|
'mystrudel', // MQTT client id - randomly generated if not supplied
|
|
0 // latency / delay before sending messages (0 = no delay)
|
|
)`}
|
|
|
|
/>
|
|
|
|
Other software can then receive the messages. For example using the [mosquitto](https://mosquitto.org/) commandline client tools:
|
|
|
|
```
|
|
|
|
> mosquitto_sub -h mqtt.eclipseprojects.io -p 1883 -t "/strudel-pattern"
|
|
> hello
|
|
> world
|
|
> hello
|
|
> world
|
|
> ...
|
|
|
|
```
|
|
|
|
Control patterns will be encoded as JSON, for example:
|
|
|
|
<MiniRepl
|
|
client:only="react"
|
|
tune={`sound("sax(3,8)").speed("2 3")
|
|
.mqtt(undefined, // username (undefined for open/public servers)
|
|
undefined, // password
|
|
'/strudel-pattern', // mqtt 'topic'
|
|
'wss://mqtt.eclipseprojects.io:443/mqtt', // MQTT server address
|
|
'mystrudel', // MQTT client id - randomly generated if not supplied
|
|
0 // latency / delay before sending messages (0 = no delay)
|
|
)`}
|
|
/>
|
|
|
|
Will send messages like the following:
|
|
|
|
```
|
|
|
|
{"s":"sax","speed":2}
|
|
{"s":"sax","speed":2}
|
|
{"s":"sax","speed":3}
|
|
{"s":"sax","speed":2}
|
|
...
|
|
|
|
```
|
|
|
|
Libraries for receiving MQTT are available for many programming languages.
|
|
|
|
```
|
|
|
|
```
|