mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-11 21:58:31 +00:00
add midichan + docs
This commit is contained in:
parent
5de6643604
commit
886f8449fd
@ -64,7 +64,7 @@ function getDevice(output, outputs) {
|
||||
}
|
||||
|
||||
// Pattern.prototype.midi = function (output: string | number, channel = 1) {
|
||||
Pattern.prototype.midi = function (output, channel = 1) {
|
||||
Pattern.prototype.midi = function (output) {
|
||||
if (!supportsMidi()) {
|
||||
throw new Error(`🎹 WebMidi is not enabled. Supported Browsers: https://caniuse.com/?search=webmidi`);
|
||||
}
|
||||
@ -109,21 +109,27 @@ Pattern.prototype.midi = function (output, channel = 1) {
|
||||
time = time * 1000 + timingOffset;
|
||||
|
||||
// destructure value
|
||||
const { note, nrpnn, nrpv, ccn, ccv } = hap.value;
|
||||
const { note, nrpnn, nrpv, ccn, ccv, midichan = 1 } = hap.value;
|
||||
const velocity = hap.context?.velocity ?? 0.9; // TODO: refactor velocity
|
||||
const duration = hap.duration.valueOf() * 1000 - 5;
|
||||
|
||||
if (note) {
|
||||
const midiNumber = toMidi(note);
|
||||
console.log('midi number', midiNumber);
|
||||
device.playNote(midiNumber, channel, {
|
||||
device.playNote(midiNumber, midichan, {
|
||||
time,
|
||||
duration,
|
||||
attack: velocity,
|
||||
});
|
||||
}
|
||||
if (ccn && ccv) {
|
||||
device.sendControlChange(ccn, ccv, channel, { time });
|
||||
if (ccv && ccn) {
|
||||
if (typeof ccv !== 'number' || ccv < 0 || ccv > 1) {
|
||||
throw new Error('expected ccv to be a number between 0 and 1');
|
||||
}
|
||||
if (!['string', 'number'].includes(typeof ccn)) {
|
||||
throw new Error('expected ccn to be a number or a string');
|
||||
}
|
||||
const scaled = Math.round(ccv * 127);
|
||||
device.sendControlChange(ccn, scaled, midichan, { time });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -22,12 +22,35 @@ If no outputName is given, it uses the first midi output it finds.
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`stack("<C^7 A7 Dm7 G7>".voicings('lefthand'), "<C3 A2 D3 G2>")
|
||||
tune={`stack("<C^7 A7 Dm7 G7>".voicings('lefthand'), "<C3 A2 D3 G2>").note()
|
||||
.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.
|
||||
|
||||
## ccn && ccv
|
||||
|
||||
- `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").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={`stack(
|
||||
note("c a f e"),
|
||||
ccv(sine.segment(16).slow(4)).ccn(74)
|
||||
).midi()`}
|
||||
/>
|
||||
|
||||
# SuperDirt API
|
||||
|
||||
In mainline tidal, the actual sound is generated via [SuperDirt](https://github.com/musikinformatik/SuperDirt/), which runs inside SuperCollider.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user