build
This commit is contained in:
parent
68b481af6e
commit
1d4129e84d
8 changed files with 94 additions and 66 deletions
|
|
@ -526,8 +526,11 @@ class Pattern {
|
||||||
_legato(value) {
|
_legato(value) {
|
||||||
return this.withEventSpan((span) => new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value))));
|
return this.withEventSpan((span) => new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value))));
|
||||||
}
|
}
|
||||||
|
_velocity(velocity) {
|
||||||
|
return this._withContext((context) => ({...context, velocity: (context.velocity || 1) * velocity}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Pattern.prototype.patternified = ["apply", "fast", "slow", "early", "late", "duration", "legato"];
|
Pattern.prototype.patternified = ["apply", "fast", "slow", "early", "late", "duration", "legato", "velocity"];
|
||||||
Pattern.prototype.factories = {pure, stack, slowcat, fastcat, cat, timeCat, sequence, polymeter, pm, polyrhythm, pr};
|
Pattern.prototype.factories = {pure, stack, slowcat, fastcat, cat, timeCat, sequence, polymeter, pm, polyrhythm, pr};
|
||||||
const silence = new Pattern((_) => []);
|
const silence = new Pattern((_) => []);
|
||||||
function pure(value) {
|
function pure(value) {
|
||||||
|
|
|
||||||
23
docs/dist/midi.js
vendored
23
docs/dist/midi.js
vendored
|
|
@ -24,12 +24,12 @@ Pattern.prototype.midi = function(output, channel = 1) {
|
||||||
if (output?.constructor?.name === "Pattern") {
|
if (output?.constructor?.name === "Pattern") {
|
||||||
throw new Error(`.midi does not accept Pattern input. Make sure to pass device name with single quotes. Example: .midi('${WebMidi.outputs?.[0]?.name || "IAC Driver Bus 1"}')`);
|
throw new Error(`.midi does not accept Pattern input. Make sure to pass device name with single quotes. Example: .midi('${WebMidi.outputs?.[0]?.name || "IAC Driver Bus 1"}')`);
|
||||||
}
|
}
|
||||||
return this.fmap((value) => ({
|
return this._withEvent((event) => {
|
||||||
...value,
|
const onTrigger = (time, event2) => {
|
||||||
onTrigger: (time, event) => {
|
let note = event2.value;
|
||||||
value = value.value || value;
|
const velocity = event2.context?.velocity ?? 0.9;
|
||||||
if (!isNote(value)) {
|
if (!isNote(note)) {
|
||||||
throw new Error("not a note: " + value);
|
throw new Error("not a note: " + note);
|
||||||
}
|
}
|
||||||
if (!WebMidi.enabled) {
|
if (!WebMidi.enabled) {
|
||||||
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`);
|
||||||
|
|
@ -43,13 +43,14 @@ Pattern.prototype.midi = function(output, channel = 1) {
|
||||||
}
|
}
|
||||||
const timingOffset = WebMidi.time - Tone.context.currentTime * 1e3;
|
const timingOffset = WebMidi.time - Tone.context.currentTime * 1e3;
|
||||||
time = time * 1e3 + timingOffset;
|
time = time * 1e3 + timingOffset;
|
||||||
device.playNote(value, channel, {
|
device.playNote(note, channel, {
|
||||||
time,
|
time,
|
||||||
duration: event.duration * 1e3 - 5,
|
duration: event2.duration * 1e3 - 5,
|
||||||
velocity: 0.9
|
velocity
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
}));
|
return event.setContext({...event.context, onTrigger});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
export function useWebMidi(props) {
|
export function useWebMidi(props) {
|
||||||
const {ready, connected, disconnected} = props;
|
const {ready, connected, disconnected} = props;
|
||||||
|
|
|
||||||
7
docs/dist/tone.js
vendored
7
docs/dist/tone.js
vendored
|
|
@ -24,6 +24,7 @@ Pattern.prototype.tone = function(instrument) {
|
||||||
return this._withEvent((event) => {
|
return this._withEvent((event) => {
|
||||||
const onTrigger = (time, event2) => {
|
const onTrigger = (time, event2) => {
|
||||||
let note = event2.value;
|
let note = event2.value;
|
||||||
|
let velocity = event2.context?.velocity ?? 0.75;
|
||||||
switch (instrument.constructor.name) {
|
switch (instrument.constructor.name) {
|
||||||
case "PluckSynth":
|
case "PluckSynth":
|
||||||
instrument.triggerAttack(note, time);
|
instrument.triggerAttack(note, time);
|
||||||
|
|
@ -33,10 +34,10 @@ Pattern.prototype.tone = function(instrument) {
|
||||||
break;
|
break;
|
||||||
case "Piano":
|
case "Piano":
|
||||||
instrument.keyDown({note, time, velocity: 0.5});
|
instrument.keyDown({note, time, velocity: 0.5});
|
||||||
instrument.keyUp({note, time: time + event2.duration});
|
instrument.keyUp({note, time: time + event2.duration, velocity});
|
||||||
break;
|
break;
|
||||||
case "Sampler":
|
case "Sampler":
|
||||||
instrument.triggerAttackRelease(note, event2.duration, time);
|
instrument.triggerAttackRelease(note, event2.duration, time, velocity);
|
||||||
break;
|
break;
|
||||||
case "Players":
|
case "Players":
|
||||||
if (!instrument.has(event2.value)) {
|
if (!instrument.has(event2.value)) {
|
||||||
|
|
@ -47,7 +48,7 @@ Pattern.prototype.tone = function(instrument) {
|
||||||
player.stop(time + event2.duration);
|
player.stop(time + event2.duration);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
instrument.triggerAttackRelease(note, event2.duration, time);
|
instrument.triggerAttackRelease(note, event2.duration, time, velocity);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return event.setContext({...event.context, instrument, onTrigger});
|
return event.setContext({...event.context, instrument, onTrigger});
|
||||||
|
|
|
||||||
41
docs/dist/tunes.js
vendored
41
docs/dist/tunes.js
vendored
|
|
@ -463,20 +463,29 @@ export const blippyRhodes = `Promise.all([
|
||||||
"<c2 c3 f2 [[F2 C2] db2]>".legato("<1@3 [.3 1]>").slow(2).tone(bass),
|
"<c2 c3 f2 [[F2 C2] db2]>".legato("<1@3 [.3 1]>").slow(2).tone(bass),
|
||||||
).fast(3/2)
|
).fast(3/2)
|
||||||
})`;
|
})`;
|
||||||
export const wavyRhodes = `sampler({
|
export const wavyKalimba = `sampler({
|
||||||
E1: 'MK2Md2000.mp3',
|
C5: 'https://freesound.org/data/previews/536/536549_11935698-lq.mp3'
|
||||||
E2: 'MK2Md2012.mp3',
|
}).then((kalimba)=>{
|
||||||
E3: 'MK2Md2024.mp3',
|
const delay = new FeedbackDelay(1/3, .5).chain(vol(.2), out());
|
||||||
E4: 'MK2Md2036.mp3',
|
kalimba = kalimba.chain(vol(0.6).connect(delay),out());
|
||||||
E5: 'MK2Md2048.mp3',
|
const scales = sequence('C major', 'C mixolydian', 'F lydian', ['F minor', 'Db major']).slow(4);
|
||||||
E6: 'MK2Md2060.mp3',
|
return stack(
|
||||||
E7: 'MK2Md2072.mp3'
|
"[0 2 4 6 9 2 0 -2]*3"
|
||||||
}, 'https://loophole-letters.vercel.app/samples/rhodes/').then((rhodes)=>{
|
.add("<0 2>/4")
|
||||||
const delay = new FeedbackDelay(1/6, .5).chain(vol(.2), out());
|
.scale(scales)
|
||||||
rhodes = rhodes.chain(vol(0.5).connect(delay), out());
|
.struct("x*8")
|
||||||
const scales = sequence('C major', 'C mixolydian', 'F lydian', ['F minor', 'Db major']).slow(4);
|
.velocity("<.8 .3 .6>*8")
|
||||||
return stack(
|
.slow(2)
|
||||||
"[0 2 4 6 9 2 0 -2]*3".add("<0 2>/4").scale(scales).struct("x*8").slow(2).tone(rhodes),
|
.tone(kalimba),
|
||||||
"<c2 c2 f2 [[F2 C2] db2]>".scale(scales).scaleTranspose("[0 <2 4>]*2").struct("x*4").slow(2).tone(rhodes),
|
"<c2 c2 f2 [[F2 C2] db2]>"
|
||||||
).legato("<.2 .4 .8 1 1.2 1.4 1.6 1.8 2>/8")
|
.scale(scales)
|
||||||
|
.scaleTranspose("[0 <2 4>]*2")
|
||||||
|
.struct("x*4")
|
||||||
|
.velocity("<.8 .5>*4")
|
||||||
|
.velocity(0.8)
|
||||||
|
.slow(2)
|
||||||
|
.tone(kalimba)
|
||||||
|
)
|
||||||
|
.legato("<.4 .8 1 1.2 1.4 1.6 1.8 2>/8")
|
||||||
|
.fast(1)
|
||||||
})`;
|
})`;
|
||||||
|
|
|
||||||
4
docs/dist/useRepl.js
vendored
4
docs/dist/useRepl.js
vendored
|
|
@ -52,14 +52,14 @@ function useRepl({tune, defaultSynth, autolink = true, onEvent, onDraw}) {
|
||||||
onEvent: useCallback((time, event) => {
|
onEvent: useCallback((time, event) => {
|
||||||
try {
|
try {
|
||||||
onEvent?.(event);
|
onEvent?.(event);
|
||||||
const {onTrigger} = event.context;
|
const {onTrigger, velocity} = event.context;
|
||||||
if (!onTrigger) {
|
if (!onTrigger) {
|
||||||
const note = event.value;
|
const note = event.value;
|
||||||
if (!isNote(note)) {
|
if (!isNote(note)) {
|
||||||
throw new Error("not a note: " + note);
|
throw new Error("not a note: " + note);
|
||||||
}
|
}
|
||||||
if (defaultSynth) {
|
if (defaultSynth) {
|
||||||
defaultSynth.triggerAttackRelease(note, event.duration, time);
|
defaultSynth.triggerAttackRelease(note, event.duration, time, velocity);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("no defaultSynth passed to useRepl.");
|
throw new Error("no defaultSynth passed to useRepl.");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41709,11 +41709,11 @@ function useRepl({ tune , defaultSynth , autolink =true , onEvent , onDraw }) {
|
||||||
onEvent: _react.useCallback((time, event)=>{
|
onEvent: _react.useCallback((time, event)=>{
|
||||||
try {
|
try {
|
||||||
onEvent?.(event);
|
onEvent?.(event);
|
||||||
const { onTrigger } = event.context;
|
const { onTrigger , velocity } = event.context;
|
||||||
if (!onTrigger) {
|
if (!onTrigger) {
|
||||||
const note = event.value;
|
const note = event.value;
|
||||||
if (!_tone.isNote(note)) throw new Error('not a note: ' + note);
|
if (!_tone.isNote(note)) throw new Error('not a note: ' + note);
|
||||||
if (defaultSynth) defaultSynth.triggerAttackRelease(note, event.duration, time);
|
if (defaultSynth) defaultSynth.triggerAttackRelease(note, event.duration, time, velocity);
|
||||||
else throw new Error('no defaultSynth passed to useRepl.');
|
else throw new Error('no defaultSynth passed to useRepl.');
|
||||||
/* console.warn('no instrument chosen', event);
|
/* console.warn('no instrument chosen', event);
|
||||||
throw new Error(`no instrument chosen for ${JSON.stringify(event)}`); */ } else onTrigger(time, event);
|
throw new Error(`no instrument chosen for ${JSON.stringify(event)}`); */ } else onTrigger(time, event);
|
||||||
|
|
@ -42641,6 +42641,13 @@ class Pattern {
|
||||||
return this.withEventSpan((span)=>new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value)))
|
return this.withEventSpan((span)=>new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
_velocity(velocity) {
|
||||||
|
return this._withContext((context)=>({
|
||||||
|
...context,
|
||||||
|
velocity: (context.velocity || 1) * velocity
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// methods of Pattern that get callable factories
|
// methods of Pattern that get callable factories
|
||||||
Pattern.prototype.patternified = [
|
Pattern.prototype.patternified = [
|
||||||
|
|
@ -42650,7 +42657,8 @@ Pattern.prototype.patternified = [
|
||||||
'early',
|
'early',
|
||||||
'late',
|
'late',
|
||||||
'duration',
|
'duration',
|
||||||
'legato'
|
'legato',
|
||||||
|
'velocity'
|
||||||
];
|
];
|
||||||
// methods that create patterns, which are added to patternified Pattern methods
|
// methods that create patterns, which are added to patternified Pattern methods
|
||||||
Pattern.prototype.factories = {
|
Pattern.prototype.factories = {
|
||||||
|
|
@ -56583,9 +56591,11 @@ Pattern.prototype.tone = function(instrument) {
|
||||||
return this._withEvent((event1)=>{
|
return this._withEvent((event1)=>{
|
||||||
const onTrigger = (time, event)=>{
|
const onTrigger = (time, event)=>{
|
||||||
let note = event.value;
|
let note = event.value;
|
||||||
|
let velocity = event.context?.velocity ?? 0.75;
|
||||||
switch(instrument.constructor.name){
|
switch(instrument.constructor.name){
|
||||||
case 'PluckSynth':
|
case 'PluckSynth':
|
||||||
// note = getPlayableNoteValue(event);
|
// note = getPlayableNoteValue(event);
|
||||||
|
// velocity?
|
||||||
instrument.triggerAttack(note, time);
|
instrument.triggerAttack(note, time);
|
||||||
break;
|
break;
|
||||||
case 'NoiseSynth':
|
case 'NoiseSynth':
|
||||||
|
|
@ -56600,22 +56610,24 @@ Pattern.prototype.tone = function(instrument) {
|
||||||
});
|
});
|
||||||
instrument.keyUp({
|
instrument.keyUp({
|
||||||
note,
|
note,
|
||||||
time: time + event.duration
|
time: time + event.duration,
|
||||||
|
velocity
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'Sampler':
|
case 'Sampler':
|
||||||
// note = getPlayableNoteValue(event);
|
// note = getPlayableNoteValue(event);
|
||||||
instrument.triggerAttackRelease(note, event.duration, time);
|
instrument.triggerAttackRelease(note, event.duration, time, velocity);
|
||||||
break;
|
break;
|
||||||
case 'Players':
|
case 'Players':
|
||||||
if (!instrument.has(event.value)) throw new Error(`name "${event.value}" not defined for players`);
|
if (!instrument.has(event.value)) throw new Error(`name "${event.value}" not defined for players`);
|
||||||
const player = instrument.player(event.value);
|
const player = instrument.player(event.value);
|
||||||
|
// velocity ?
|
||||||
player.start(time);
|
player.start(time);
|
||||||
player.stop(time + event.duration);
|
player.stop(time + event.duration);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// note = getPlayableNoteValue(event);
|
// note = getPlayableNoteValue(event);
|
||||||
instrument.triggerAttackRelease(note, event.duration, time);
|
instrument.triggerAttackRelease(note, event.duration, time, velocity);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return event1.setContext({
|
return event1.setContext({
|
||||||
|
|
@ -59361,30 +59373,32 @@ const outputByName = (name)=>WebMidi.getOutputByName(name)
|
||||||
;
|
;
|
||||||
Pattern.prototype.midi = function(output, channel = 1) {
|
Pattern.prototype.midi = function(output, channel = 1) {
|
||||||
if (output?.constructor?.name === 'Pattern') throw new Error(`.midi does not accept Pattern input. Make sure to pass device name with single quotes. Example: .midi('${WebMidi.outputs?.[0]?.name || 'IAC Driver Bus 1'}')`);
|
if (output?.constructor?.name === 'Pattern') throw new Error(`.midi does not accept Pattern input. Make sure to pass device name with single quotes. Example: .midi('${WebMidi.outputs?.[0]?.name || 'IAC Driver Bus 1'}')`);
|
||||||
return this.fmap((value)=>({
|
return this._withEvent((event1)=>{
|
||||||
...value,
|
const onTrigger = (time, event)=>{
|
||||||
onTrigger: (time, event)=>{
|
let note = event.value;
|
||||||
value = value.value || value;
|
const velocity = event.context?.velocity ?? 0.9;
|
||||||
if (!_tone.isNote(value)) throw new Error('not a note: ' + value);
|
if (!_tone.isNote(note)) throw new Error('not a note: ' + note);
|
||||||
if (!WebMidi.enabled) throw new Error(`🎹 WebMidi is not enabled. Supported Browsers: https://caniuse.com/?search=webmidi`);
|
if (!WebMidi.enabled) throw new Error(`🎹 WebMidi is not enabled. Supported Browsers: https://caniuse.com/?search=webmidi`);
|
||||||
if (!WebMidi.outputs.length) throw new Error(`🔌 No MIDI devices found. Connect a device or enable IAC Driver.`);
|
if (!WebMidi.outputs.length) throw new Error(`🔌 No MIDI devices found. Connect a device or enable IAC Driver.`);
|
||||||
const device = output ? outputByName(output) : WebMidi.outputs[0];
|
const device = output ? outputByName(output) : WebMidi.outputs[0];
|
||||||
if (!device) throw new Error(`🔌 MIDI device '${output ? output : ''}' not found. Use one of ${WebMidi.outputs.map((o)=>`'${o.name}'`
|
if (!device) throw new Error(`🔌 MIDI device '${output ? output : ''}' not found. Use one of ${WebMidi.outputs.map((o)=>`'${o.name}'`
|
||||||
).join(' | ')}`);
|
).join(' | ')}`);
|
||||||
// console.log('midi', value, output);
|
// console.log('midi', value, output);
|
||||||
const timingOffset = WebMidi.time - _tone.context.currentTime * 1000;
|
const timingOffset = WebMidi.time - _tone.context.currentTime * 1000;
|
||||||
time = time * 1000 + timingOffset;
|
time = time * 1000 + timingOffset;
|
||||||
// const inMs = '+' + (time - Tone.context.currentTime) * 1000;
|
// const inMs = '+' + (time - Tone.context.currentTime) * 1000;
|
||||||
// await enableWebMidi()
|
// await enableWebMidi()
|
||||||
device.playNote(value, channel, {
|
device.playNote(note, channel, {
|
||||||
time,
|
time,
|
||||||
duration: event.duration * 1000 - 5,
|
duration: event.duration * 1000 - 5,
|
||||||
// velocity: velocity ?? 0.5,
|
velocity
|
||||||
velocity: 0.9
|
});
|
||||||
});
|
};
|
||||||
}
|
return event1.setContext({
|
||||||
})
|
...event1.context,
|
||||||
);
|
onTrigger
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
function useWebMidi(props) {
|
function useWebMidi(props) {
|
||||||
const { ready , connected , disconnected } = props;
|
const { ready , connected , disconnected } = props;
|
||||||
|
|
@ -110944,4 +110958,4 @@ exports.default = cx;
|
||||||
|
|
||||||
},{"@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}]},["3uVTb"], "3uVTb", "parcelRequire94c2")
|
},{"@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}]},["3uVTb"], "3uVTb", "parcelRequire94c2")
|
||||||
|
|
||||||
//# sourceMappingURL=index.dc7f72be.js.map
|
//# sourceMappingURL=index.23fc2d31.js.map
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -11,6 +11,6 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<script src="/tutorial/index.dc7f72be.js" defer=""></script>
|
<script src="/tutorial/index.23fc2d31.js" defer=""></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue