This commit is contained in:
Felix Roos
2022-02-27 12:08:23 +01:00
parent ef3ab6161f
commit 9442b5c66b
9 changed files with 107 additions and 90 deletions
@@ -7330,12 +7330,12 @@ It aims to be `, /*#__PURE__*/ _react1.mdx("a", {
"href": "https://strudel.tidalcycles.org/"
}, `Strudel REPL`), `.`), /*#__PURE__*/ _react1.mdx("h2", null, `Show me a Demo`), /*#__PURE__*/ _react1.mdx("p", null, `To get a taste of what Strudel can do, check out this track:`), /*#__PURE__*/ _react1.mdx(_miniReplDefault.default, {
tune: `() => {
const delay = new FeedbackDelay(1/8, .4).chain(vol(0.5), out);
const kick = new MembraneSynth().chain(vol(.8), out);
const snare = new NoiseSynth().chain(vol(.8), out);
const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out);
const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out);
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out);
const delay = new FeedbackDelay(1/8, .4).chain(vol(0.5), out());
const kick = new MembraneSynth().chain(vol(.8), out());
const snare = new NoiseSynth().chain(vol(.8), out());
const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out());
const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out());
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out());
const drums = stack(
"c1*2".tone(kick).bypass("<0@7 1>/8"),
@@ -7577,12 +7577,12 @@ For sharp notes, the letter "s" is used instead of "#", because JavaScript does
}, `Show Source on Github`)), /*#__PURE__*/ _react1.mdx(_miniReplDefault.default, {
tune: `stack(
"[c5 c5 bb4 c5] [~ g4 ~ g4] [c5 f5 e5 c5] ~"
.tone(synth(adsr(0,.1,0,0)).chain(out)),
.tone(synth(adsr(0,.1,0,0)).chain(out())),
"[c2 c3]*8"
.tone(synth({
...osc('sawtooth'),
...adsr(0,.1,0.4,0)
}).chain(lowpass(300), out))
}).chain(lowpass(300), out()))
).slow(4)`,
mdxType: "MiniRepl"
}), /*#__PURE__*/ _react1.mdx("h3", null, `tone(instrument)`), /*#__PURE__*/ _react1.mdx("p", null, `To change the instrument of a pattern, you can pass any `, /*#__PURE__*/ _react1.mdx("a", {
@@ -7608,15 +7608,15 @@ const sampler = (options) => new Sampler(options);
const synth = (options) => new Synth(options);
`)), /*#__PURE__*/ _react1.mdx("h3", null, `out`), /*#__PURE__*/ _react1.mdx("p", null, `Shortcut for Tone.Destination. Intended to be used with Tone's .chain:`), /*#__PURE__*/ _react1.mdx(_miniReplDefault.default, {
tune: `"[c4 c4 bb3 c4] [~ g3 ~ g3] [c4 f4 e4 c4] ~".slow(4)
.tone(membrane().chain(out))`,
.tone(membrane().chain(out()))`,
mdxType: "MiniRepl"
}), /*#__PURE__*/ _react1.mdx("p", null, `This alone is not really useful, so read on..`), /*#__PURE__*/ _react1.mdx("h3", null, `vol(volume)`), /*#__PURE__*/ _react1.mdx("p", null, `Helper that returns a Gain Node with the given volume. Intended to be used with Tone's .chain:`), /*#__PURE__*/ _react1.mdx(_miniReplDefault.default, {
tune: `"[c4 c4 bb3 c4] [~ g3 ~ g3] [c4 f4 e4 c4] ~".slow(4)
.tone(noise().chain(vol(0.5), out))`,
.tone(noise().chain(vol(0.5), out()))`,
mdxType: "MiniRepl"
}), /*#__PURE__*/ _react1.mdx("h3", null, `osc(type)`), /*#__PURE__*/ _react1.mdx("p", null, `Helper to set the waveform of a synth, monosynth or polysynth:`), /*#__PURE__*/ _react1.mdx(_miniReplDefault.default, {
tune: `"[c4 c4 bb3 c4] [~ g3 ~ g3] [c4 f4 e4 c4] ~".slow(4)
.tone(synth(osc('sawtooth4')).chain(out))`,
.tone(synth(osc('sawtooth4')).chain(out()))`,
mdxType: "MiniRepl"
}), /*#__PURE__*/ _react1.mdx("p", null, `The base types are `, /*#__PURE__*/ _react1.mdx("inlineCode", {
parentName: "p"
@@ -7628,15 +7628,15 @@ const synth = (options) => new Synth(options);
parentName: "p"
}, `triangle`), `. You can also append a number between 1 and 32 to reduce the harmonic partials.`), /*#__PURE__*/ _react1.mdx("h3", null, `lowpass(cutoff)`), /*#__PURE__*/ _react1.mdx("p", null, `Helper that returns a Filter Node of type lowpass with the given cutoff. Intended to be used with Tone's .chain:`), /*#__PURE__*/ _react1.mdx(_miniReplDefault.default, {
tune: `"[c4 c4 bb3 c4] [~ g3 ~ g3] [c4 f4 e4 c4] ~".slow(4)
.tone(synth(osc('sawtooth')).chain(lowpass(800), out))`,
.tone(synth(osc('sawtooth')).chain(lowpass(800), out()))`,
mdxType: "MiniRepl"
}), /*#__PURE__*/ _react1.mdx("h3", null, `highpass(cutoff)`), /*#__PURE__*/ _react1.mdx("p", null, `Helper that returns a Filter Node of type highpass with the given cutoff. Intended to be used with Tone's .chain:`), /*#__PURE__*/ _react1.mdx(_miniReplDefault.default, {
tune: `"[c4 c4 bb3 c4] [~ g3 ~ g3] [c4 f4 e4 c4] ~".slow(4)
.tone(synth(osc('sawtooth')).chain(highpass(2000), out))`,
.tone(synth(osc('sawtooth')).chain(highpass(2000), out()))`,
mdxType: "MiniRepl"
}), /*#__PURE__*/ _react1.mdx("h3", null, `adsr(attack, decay?, sustain?, release?)`), /*#__PURE__*/ _react1.mdx("p", null, `Helper to set the envelope of a Tone.js instrument. Intended to be used with Tone's .set:`), /*#__PURE__*/ _react1.mdx(_miniReplDefault.default, {
tune: `"[c4 c4 bb3 c4] [~ g3 ~ g3] [c4 f4 e4 c4] ~".slow(4)
.tone(synth(adsr(0,.1,0,0)).chain(out))`,
.tone(synth(adsr(0,.1,0,0)).chain(out()))`,
mdxType: "MiniRepl"
}), /*#__PURE__*/ _react1.mdx("h3", null, `Experimental: Patternification`), /*#__PURE__*/ _react1.mdx("p", null, `While the above methods work for static sounds, there is also the option to patternify tone methods.
This is currently experimental, because the performance is not stable, and audio glitches will appear after some time.
@@ -7690,7 +7690,7 @@ It would be great to get this to work without glitches though, because it is fun
}), /*#__PURE__*/ _react1.mdx("p", null, `Together with edit, struct and voicings, this can be used to create a basic backing track:`), /*#__PURE__*/ _react1.mdx(_miniReplDefault.default, {
tune: `"<C^7 A7b13 Dm7 G7>".edit(
x => x.voicings(['d3','g4']).struct("~ x"),
x => x.rootNotes(2).tone(synth(osc('sawtooth4')).chain(out))
x => x.rootNotes(2).tone(synth(osc('sawtooth4')).chain(out()))
)`,
mdxType: "MiniRepl"
}), /*#__PURE__*/ _react1.mdx("p", null, `TODO: use range instead of octave.
@@ -7946,13 +7946,18 @@ const defaultSynth = new _tone.PolySynth().chain(new _tone.Gain(0.5), _tone.Dest
release: 0.01
}
});
// "balanced" | "interactive" | "playback";
_tone.setContext(new _tone.Context({
latencyHint: 'playback',
lookAhead: 1
}));
function MiniRepl({ tune , maxHeight =500 }) {
const [editor, setEditor] = _react.useState();
const { code , setCode , activateCode , activeCode , setPattern , error , cycle , dirty , log , togglePlay , hash } = _useReplDefault.default({
tune,
defaultSynth,
autolink: false,
onEvent: _react.useCallback(_codeMirror.markEvent(editor), [
onDraw: _react.useCallback(_codeMirror.markEvent(editor), [
editor
])
});
@@ -41655,7 +41660,7 @@ var _usePostMessageDefault = parcelHelpers.interopDefault(_usePostMessage);
let s4 = ()=>{
return Math.floor((1 + Math.random()) * 65536).toString(16).substring(1);
};
function useRepl({ tune , defaultSynth , autolink =true , onEvent }) {
function useRepl({ tune , defaultSynth , autolink =true , onEvent , onDraw }) {
const id = _react.useMemo(()=>s4()
, []);
const [code, setCode] = _react.useState(tune);
@@ -41700,6 +41705,7 @@ function useRepl({ tune , defaultSynth , autolink =true , onEvent }) {
};
// cycle hook to control scheduling
const cycle1 = _useCycleDefault.default({
onDraw,
onEvent: _react.useCallback((time, event)=>{
try {
onEvent?.(event);
@@ -41725,6 +41731,7 @@ function useRepl({ tune , defaultSynth , autolink =true , onEvent }) {
try {
return pattern?.query(span) || [];
} catch (err) {
console.warn(err);
err.message = 'query error: ' + err.message;
setError(err);
return [];
@@ -56548,7 +56555,8 @@ const osc = (type)=>({
}
})
;
const out = _tone.Destination;
const out = ()=>_tone.getDestination()
;
/*
You are entering experimental zone
@@ -56560,7 +56568,7 @@ const chainable = function(instr) {
instr.chain = (...args)=>{
chained = chained.concat(args);
instr.disconnect(); // disconnect from destination / previous chain
return _chain(...chained, _tone.Destination);
return _chain(...chained, _tone.getDestination());
};
// shortcuts: chaining multiple won't work forn now.. like filter(1000).gain(0.5). use chain + native Tone calls instead
instr.filter = (freq = 1000, type = 'lowpass')=>instr.chain(new _tone.Filter(freq, type) // .Q.setValueAtTime(q, time);
@@ -56693,7 +56701,7 @@ Pattern.prototype.chain = function(...effectGetters) {
const getChain = ()=>{
const effects = chain.map((getEffect)=>getEffect()
);
return value.getInstrument().chain(...effects, _tone.Destination);
return value.getInstrument().chain(...effects, _tone.getDestination());
};
const onTrigger = getTrigger(getChain, value.value);
return {
@@ -98097,10 +98105,10 @@ var _tone = require("tone");
var _strudelMjs = require("../../strudel.mjs");
function useCycle(props) {
// onX must use useCallback!
const { onEvent , onQuery , onSchedule , ready =true } = props;
const { onEvent , onQuery , onSchedule , ready =true , onDraw } = props;
const [started, setStarted] = _react.useState(false);
const cycleDuration = 1;
const activeCycle = ()=>Math.floor(_tone.Transport.seconds / cycleDuration)
const activeCycle = ()=>Math.floor(_tone.getTransport().seconds / cycleDuration)
;
// pull events with onQuery + count up to next cycle
const query = (cycle = activeCycle())=>{
@@ -98111,24 +98119,28 @@ function useCycle(props) {
// console.log('schedule', cycle);
// query next cycle in the middle of the current
const cancelFrom = timespan.begin.valueOf();
_tone.Transport.cancel(cancelFrom);
_tone.getTransport().cancel(cancelFrom);
// const queryNextTime = (cycle + 1) * cycleDuration - 0.1;
const queryNextTime = (cycle + 1) * cycleDuration - 0.5;
// if queryNextTime would be before current time, execute directly (+0.1 for safety that it won't miss)
const t = Math.max(_tone.Transport.seconds, queryNextTime) + 0.1;
_tone.Transport.schedule(()=>{
const t = Math.max(_tone.getTransport().seconds, queryNextTime) + 0.1;
_tone.getTransport().schedule(()=>{
query(cycle + 1);
}, t);
// schedule events for next cycle
events?.filter((event)=>event.part.begin.valueOf() === event.whole.begin.valueOf()
).forEach((event)=>{
_tone.Transport.schedule((time)=>{
_tone.getTransport().schedule((time)=>{
const toneEvent = {
time: event.part.begin.valueOf(),
duration: event.whole.end.sub(event.whole.begin).valueOf(),
value: event.value
};
onEvent(time, toneEvent);
_tone.Draw.schedule(()=>{
// do drawing or DOM manipulation here
onDraw?.(time, toneEvent);
}, time);
}, event.part.begin.valueOf());
});
};
@@ -98143,12 +98155,12 @@ function useCycle(props) {
const start = async ()=>{
setStarted(true);
await _tone.start();
_tone.Transport.start('+0.1');
_tone.getTransport().start('+0.1');
};
const stop = ()=>{
console.log('stop');
setStarted(false);
_tone.Transport.pause();
_tone.getTransport().pause();
};
const toggle = ()=>started ? stop() : start()
;
@@ -98212,7 +98224,7 @@ function CodeMirror({ value , onChange , options , editorDidMount }) {
}));
}
exports.default = CodeMirror;
const markEvent = (editor)=>(event)=>{
const markEvent = (editor)=>(time, event)=>{
const locs = event.value.locations;
if (!locs || !editor) return;
// mark active event
@@ -109452,4 +109464,4 @@ exports.default = cx;
},{"@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}]},["3uVTb"], "3uVTb", "parcelRequire94c2")
//# sourceMappingURL=index.8834957f.js.map
//# sourceMappingURL=index.4ae5d228.js.map
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -11,6 +11,6 @@
<body>
<div id="root"></div>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script src="/tutorial/index.8834957f.js" defer=""></script>
<script src="/tutorial/index.4ae5d228.js" defer=""></script>
</body>
</html>