mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-27 05:28:41 +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: string | number, channel = 1) {
|
||||||
Pattern.prototype.midi = function (output, channel = 1) {
|
Pattern.prototype.midi = function (output) {
|
||||||
if (!supportsMidi()) {
|
if (!supportsMidi()) {
|
||||||
throw new Error(`🎹 WebMidi is not enabled. Supported Browsers: https://caniuse.com/?search=webmidi`);
|
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;
|
time = time * 1000 + timingOffset;
|
||||||
|
|
||||||
// destructure value
|
// 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 velocity = hap.context?.velocity ?? 0.9; // TODO: refactor velocity
|
||||||
const duration = hap.duration.valueOf() * 1000 - 5;
|
const duration = hap.duration.valueOf() * 1000 - 5;
|
||||||
|
|
||||||
if (note) {
|
if (note) {
|
||||||
const midiNumber = toMidi(note);
|
const midiNumber = toMidi(note);
|
||||||
console.log('midi number', midiNumber);
|
device.playNote(midiNumber, midichan, {
|
||||||
device.playNote(midiNumber, channel, {
|
|
||||||
time,
|
time,
|
||||||
duration,
|
duration,
|
||||||
attack: velocity,
|
attack: velocity,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (ccn && ccv) {
|
if (ccv && ccn) {
|
||||||
device.sendControlChange(ccn, ccv, channel, { time });
|
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
|
<MiniRepl
|
||||||
client:idle
|
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()`}
|
.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".`
|
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
|
# SuperDirt API
|
||||||
|
|
||||||
In mainline tidal, the actual sound is generated via [SuperDirt](https://github.com/musikinformatik/SuperDirt/), which runs inside SuperCollider.
|
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