build
This commit is contained in:
parent
5fb31c2a9f
commit
9ccc78a929
11 changed files with 508 additions and 458 deletions
|
|
@ -140,7 +140,7 @@ class Hap {
|
||||||
return this.spanEquals(other) && this.part.equals(other.part) && this.value === other.value;
|
return this.spanEquals(other) && this.part.equals(other.part) && this.value === other.value;
|
||||||
}
|
}
|
||||||
show() {
|
show() {
|
||||||
return "(" + (this.whole == void 0 ? "~" : this.whole.show()) + ", " + this.part.show() + ", " + this.value + ")";
|
return "(" + (this.whole == void 0 ? "~" : this.whole.show()) + ", " + this.part.show() + ", " + JSON.stringify(this.value?.value ?? this.value) + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Pattern {
|
class Pattern {
|
||||||
|
|
@ -434,7 +434,7 @@ class Pattern {
|
||||||
};
|
};
|
||||||
const left = this.withValue((val) => Object.assign({}, val, {pan: elem_or(val, "pan", 0.5) - by}));
|
const left = this.withValue((val) => Object.assign({}, val, {pan: elem_or(val, "pan", 0.5) - by}));
|
||||||
const right = this.withValue((val) => Object.assign({}, val, {pan: elem_or(val, "pan", 0.5) + by}));
|
const right = this.withValue((val) => Object.assign({}, val, {pan: elem_or(val, "pan", 0.5) + by}));
|
||||||
return stack([left, func(right)]);
|
return stack(left, func(right));
|
||||||
}
|
}
|
||||||
stack(...pats) {
|
stack(...pats) {
|
||||||
return stack(this, ...pats);
|
return stack(this, ...pats);
|
||||||
|
|
|
||||||
8
docs/dist/App.js
vendored
8
docs/dist/App.js
vendored
|
|
@ -56,13 +56,13 @@ function App() {
|
||||||
}, [pattern, code]);
|
}, [pattern, code]);
|
||||||
useWebMidi({
|
useWebMidi({
|
||||||
ready: useCallback(({outputs}) => {
|
ready: useCallback(({outputs}) => {
|
||||||
pushLog(`WebMidi ready! Just add .midi(${outputs.map((o) => `"${o.name}"`).join(" | ")}) to the pattern. `);
|
pushLog(`WebMidi ready! Just add .midi(${outputs.map((o) => `'${o.name}'`).join(" | ")}) to the pattern. `);
|
||||||
}, []),
|
}, []),
|
||||||
connected: useCallback(({outputs}) => {
|
connected: useCallback(({outputs}) => {
|
||||||
pushLog(`Midi device connected! Available: ${outputs.map((o) => `"${o.name}"`).join(", ")}`);
|
pushLog(`Midi device connected! Available: ${outputs.map((o) => `'${o.name}'`).join(", ")}`);
|
||||||
}, []),
|
}, []),
|
||||||
disconnected: useCallback(({outputs}) => {
|
disconnected: useCallback(({outputs}) => {
|
||||||
pushLog(`Midi device disconnected! Available: ${outputs.map((o) => `"${o.name}"`).join(", ")}`);
|
pushLog(`Midi device disconnected! Available: ${outputs.map((o) => `'${o.name}'`).join(", ")}`);
|
||||||
}, [])
|
}, [])
|
||||||
});
|
});
|
||||||
return /* @__PURE__ */ React.createElement("div", {
|
return /* @__PURE__ */ React.createElement("div", {
|
||||||
|
|
@ -111,7 +111,7 @@ function App() {
|
||||||
}, !cycle.started ? `press ctrl+enter to play
|
}, !cycle.started ? `press ctrl+enter to play
|
||||||
` : dirty ? `ctrl+enter to update
|
` : dirty ? `ctrl+enter to update
|
||||||
` : "no changes\n")), error && /* @__PURE__ */ React.createElement("div", {
|
` : "no changes\n")), error && /* @__PURE__ */ React.createElement("div", {
|
||||||
className: cx("absolute right-2 bottom-2", "text-red-500")
|
className: cx("absolute right-2 bottom-2 px-2", "text-red-500")
|
||||||
}, error?.message || "unknown error")), /* @__PURE__ */ React.createElement("button", {
|
}, error?.message || "unknown error")), /* @__PURE__ */ React.createElement("button", {
|
||||||
className: "flex-none w-full border border-gray-700 p-2 bg-slate-700 hover:bg-slate-500",
|
className: "flex-none w-full border border-gray-700 p-2 bg-slate-700 hover:bg-slate-500",
|
||||||
onClick: () => togglePlay()
|
onClick: () => togglePlay()
|
||||||
|
|
|
||||||
5
docs/dist/midi.js
vendored
5
docs/dist/midi.js
vendored
|
|
@ -21,6 +21,9 @@ export default function enableWebMidi() {
|
||||||
}
|
}
|
||||||
const outputByName = (name) => WebMidi.getOutputByName(name);
|
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"}')`);
|
||||||
|
}
|
||||||
return this.fmap((value) => ({
|
return this.fmap((value) => ({
|
||||||
...value,
|
...value,
|
||||||
onTrigger: (time, event) => {
|
onTrigger: (time, event) => {
|
||||||
|
|
@ -36,7 +39,7 @@ Pattern.prototype.midi = function(output, channel = 1) {
|
||||||
}
|
}
|
||||||
const device = output ? outputByName(output) : WebMidi.outputs[0];
|
const device = output ? outputByName(output) : WebMidi.outputs[0];
|
||||||
if (!device) {
|
if (!device) {
|
||||||
throw new Error(`🔌 MIDI device ${output ? output : ""} not found. Use one of ${WebMidi.outputs.map((o) => `"${o.name}"`).join(" | ")}`);
|
throw new Error(`🔌 MIDI device '${output ? output : ""}' not found. Use one of ${WebMidi.outputs.map((o) => `'${o.name}'`).join(" | ")}`);
|
||||||
}
|
}
|
||||||
const timingOffset = WebMidi.time - Tone.context.currentTime * 1e3;
|
const timingOffset = WebMidi.time - Tone.context.currentTime * 1e3;
|
||||||
time = time * 1e3 + timingOffset;
|
time = time * 1e3 + timingOffset;
|
||||||
|
|
|
||||||
5
docs/dist/shapeshifter.js
vendored
5
docs/dist/shapeshifter.js
vendored
|
|
@ -91,7 +91,9 @@ export default (code) => {
|
||||||
const isMarkable = isPatternArg(parents) || hasModifierCall(parent);
|
const isMarkable = isPatternArg(parents) || hasModifierCall(parent);
|
||||||
// add to location to pure(x) calls
|
// add to location to pure(x) calls
|
||||||
if (node.type === 'CallExpression' && node.callee.name === 'pure') {
|
if (node.type === 'CallExpression' && node.callee.name === 'pure') {
|
||||||
return reifyWithLocation(node.arguments[0].name, node.arguments[0], ast.locations, artificialNodes);
|
const literal = node.arguments[0];
|
||||||
|
const value = literal[{ LiteralNumericExpression: 'value', LiteralStringExpression: 'name' }[literal.type]];
|
||||||
|
return reifyWithLocation(value + '', node.arguments[0], ast.locations, artificialNodes);
|
||||||
}
|
}
|
||||||
// replace pseudo note variables
|
// replace pseudo note variables
|
||||||
if (node.type === 'IdentifierExpression') {
|
if (node.type === 'IdentifierExpression') {
|
||||||
|
|
@ -339,4 +341,3 @@ function getLocationObject(node, locations) {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
185
docs/dist/tunes.js
vendored
185
docs/dist/tunes.js
vendored
|
|
@ -54,49 +54,27 @@ export const tetrisWithFunctions = `stack(sequence(
|
||||||
)
|
)
|
||||||
).slow(16)`;
|
).slow(16)`;
|
||||||
export const tetris = `stack(
|
export const tetris = `stack(
|
||||||
cat(
|
cat(
|
||||||
"e5 [b4 c5] d5 [c5 b4]",
|
"e5 [b4 c5] d5 [c5 b4]",
|
||||||
"a4 [a4 c5] e5 [d5 c5]",
|
"a4 [a4 c5] e5 [d5 c5]",
|
||||||
"b4 [~ c5] d5 e5",
|
"b4 [~ c5] d5 e5",
|
||||||
"c5 a4 a4 ~",
|
"c5 a4 a4 ~",
|
||||||
"[~ d5] [~ f5] a5 [g5 f5]",
|
"[~ d5] [~ f5] a5 [g5 f5]",
|
||||||
"e5 [~ c5] e5 [d5 c5]",
|
"e5 [~ c5] e5 [d5 c5]",
|
||||||
"b4 [b4 c5] d5 e5",
|
"b4 [b4 c5] d5 e5",
|
||||||
"c5 a4 a4 ~"
|
"c5 a4 a4 ~"
|
||||||
),
|
),
|
||||||
cat(
|
cat(
|
||||||
"e2 e3 e2 e3 e2 e3 e2 e3",
|
"e2 e3 e2 e3 e2 e3 e2 e3",
|
||||||
"a2 a3 a2 a3 a2 a3 a2 a3",
|
"a2 a3 a2 a3 a2 a3 a2 a3",
|
||||||
"g#2 g#3 g#2 g#3 e2 e3 e2 e3",
|
"g#2 g#3 g#2 g#3 e2 e3 e2 e3",
|
||||||
"a2 a3 a2 a3 a2 a3 b1 c2",
|
"a2 a3 a2 a3 a2 a3 b1 c2",
|
||||||
"d2 d3 d2 d3 d2 d3 d2 d3",
|
"d2 d3 d2 d3 d2 d3 d2 d3",
|
||||||
"c2 c3 c2 c3 c2 c3 c2 c3",
|
"c2 c3 c2 c3 c2 c3 c2 c3",
|
||||||
"b1 b2 b1 b2 e2 e3 e2 e3",
|
"b1 b2 b1 b2 e2 e3 e2 e3",
|
||||||
"a1 a2 a1 a2 a1 a2 a1 a2",
|
"a1 a2 a1 a2 a1 a2 a1 a2",
|
||||||
)
|
)
|
||||||
).slow(16)`;
|
).slow(16)`;
|
||||||
export const tetrisRev = `stack(
|
|
||||||
cat(
|
|
||||||
"e5 [b4 c5] d5 [c5 b4]",
|
|
||||||
"a4 [a4 c5] e5 [d5 c5]",
|
|
||||||
"b4 [~ c5] d5 e5",
|
|
||||||
"c5 a4 a4 ~",
|
|
||||||
"[~ d5] [~ f5] a5 [g5 f5]",
|
|
||||||
"e5 [~ c5] e5 [d5 c5]",
|
|
||||||
"b4 [b4 c5] d5 e5",
|
|
||||||
"c5 a4 a4 ~",
|
|
||||||
).rev(),
|
|
||||||
cat(
|
|
||||||
"e2 e3 e2 e3 e2 e3 e2 e3",
|
|
||||||
"a2 a3 a2 a3 a2 a3 a2 a3",
|
|
||||||
"g#2 g#3 g#2 g#3 e2 e3 e2 e3",
|
|
||||||
"a2 a3 a2 a3 a2 a3 b1 c2",
|
|
||||||
"d2 d3 d2 d3 d2 d3 d2 d3",
|
|
||||||
"c2 c3 c2 c3 c2 c3 c2 c3",
|
|
||||||
"b1 b2 b1 b2 e2 e3 e2 e3",
|
|
||||||
"a1 a2 a1 a2 a1 a2 a1 a2",
|
|
||||||
).rev()
|
|
||||||
).slow(16)`;
|
|
||||||
export const tetrisMini = `\`[[e5 [b4 c5] d5 [c5 b4]]
|
export const tetrisMini = `\`[[e5 [b4 c5] d5 [c5 b4]]
|
||||||
[a4 [a4 c5] e5 [d5 c5]]
|
[a4 [a4 c5] e5 [d5 c5]]
|
||||||
[b4 [~ c5] d5 e5]
|
[b4 [~ c5] d5 e5]
|
||||||
|
|
@ -114,12 +92,6 @@ export const tetrisMini = `\`[[e5 [b4 c5] d5 [c5 b4]]
|
||||||
[[b1 b2]*2 [e2 e3]*2]
|
[[b1 b2]*2 [e2 e3]*2]
|
||||||
[[a1 a2]*4]\`.slow(16)
|
[[a1 a2]*4]\`.slow(16)
|
||||||
`;
|
`;
|
||||||
export const spanish = `slowcat(
|
|
||||||
stack(c4,eb4,g4),
|
|
||||||
stack(bb3,d4,f4),
|
|
||||||
stack(ab3,c4,eb4),
|
|
||||||
stack(g3,b3,d4)
|
|
||||||
)`;
|
|
||||||
export const whirlyStrudel = `sequence(e4, [b2, b3], c4)
|
export const whirlyStrudel = `sequence(e4, [b2, b3], c4)
|
||||||
.every(4, fast(2))
|
.every(4, fast(2))
|
||||||
.every(3, slow(1.5))
|
.every(3, slow(1.5))
|
||||||
|
|
@ -255,13 +227,6 @@ export const magicSofa = `stack(
|
||||||
.voicings(),
|
.voicings(),
|
||||||
"<c2 f2 g2> <d2 g2 a2 e2>"
|
"<c2 f2 g2> <d2 g2 a2 e2>"
|
||||||
).slow(1).transpose.slowcat(0, 2, 3, 4)`;
|
).slow(1).transpose.slowcat(0, 2, 3, 4)`;
|
||||||
export const confusedPhoneDynamic = `stack("[g2 ~@1.3] [c3 ~@1.3]".slow(2))
|
|
||||||
.superimpose(
|
|
||||||
...[-12,7,10,12,24].slice(0,5).map((t,i,{length}) => x => transpose(t,x).late(i/length))
|
|
||||||
)
|
|
||||||
.scale(sequence('C dorian', 'C mixolydian').slow(4))
|
|
||||||
.scaleTranspose(slowcat(0,1,2,1).slow(2))
|
|
||||||
.synth('triangle').gain(0.5).filter(1500)`;
|
|
||||||
export const confusedPhone = `"[g2 ~@1.3] [c3 ~@1.3]"
|
export const confusedPhone = `"[g2 ~@1.3] [c3 ~@1.3]"
|
||||||
.superimpose(
|
.superimpose(
|
||||||
transpose(-12).late(0),
|
transpose(-12).late(0),
|
||||||
|
|
@ -309,21 +274,21 @@ export const loungerave = `() => {
|
||||||
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out);
|
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out);
|
||||||
|
|
||||||
const drums = stack(
|
const drums = stack(
|
||||||
"c1*2".tone(kick).bypass("<0@7 1>/8"),
|
"c1*2".tone(kick).mask("<x@7 ~>/8"),
|
||||||
"~ <x!7 [x@3 x]>".tone(snare).bypass("<0@7 1>/4"),
|
"~ <x!7 [x@3 x]>".tone(snare).mask("<x@7 ~>/4"),
|
||||||
"[~ c4]*2".tone(hihat)
|
"[~ c4]*2".tone(hihat)
|
||||||
);
|
);
|
||||||
|
|
||||||
const thru = (x) => x.transpose("<0 1>/8").transpose(1);
|
const thru = (x) => x.transpose("<0 1>/8").transpose(1);
|
||||||
const synths = stack(
|
const synths = stack(
|
||||||
"<C2 Bb1 Ab1 [G1 [G2 G1]]>/2".struct("[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2").edit(thru).tone(bass),
|
"<C2 Bb1 Ab1 [G1 [G2 G1]]>/2".struct("[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2").edit(thru).tone(bass),
|
||||||
"<Cm7 Bb7 Fm7 G7b9>/2".struct("~ [x@0.1 ~]").voicings().edit(thru).every(2, early(1/4)).tone(keys).bypass("<0@7 1>/8".early(1/4))
|
"<Cm7 Bb7 Fm7 G7b9>/2".struct("~ [x@0.1 ~]").voicings().edit(thru).every(2, early(1/4)).tone(keys).mask("<x@7 ~>/8".early(1/4))
|
||||||
)
|
)
|
||||||
return stack(
|
return stack(
|
||||||
drums,
|
drums,
|
||||||
synths
|
synths
|
||||||
)
|
)
|
||||||
//.bypass("<0 1>*4")
|
//.mask("<x ~>*4")
|
||||||
//.early("0.25 0");
|
//.early("0.25 0");
|
||||||
}`;
|
}`;
|
||||||
export const caverave = `() => {
|
export const caverave = `() => {
|
||||||
|
|
@ -335,8 +300,8 @@ export const caverave = `() => {
|
||||||
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out);
|
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out);
|
||||||
|
|
||||||
const drums = stack(
|
const drums = stack(
|
||||||
"c1*2".tone(kick).bypass("<0@7 1>/8"),
|
"c1*2".tone(kick).mask("<x@7 ~>/8"),
|
||||||
"~ <x!7 [x@3 x]>".tone(snare).bypass("<0@7 1>/4"),
|
"~ <x!7 [x@3 x]>".tone(snare).mask("<x@7 ~>/4"),
|
||||||
"[~ c4]*2".tone(hihat)
|
"[~ c4]*2".tone(hihat)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -348,9 +313,9 @@ export const caverave = `() => {
|
||||||
scaleTranspose(2).early(1/8),
|
scaleTranspose(2).early(1/8),
|
||||||
scaleTranspose(7).early(1/4),
|
scaleTranspose(7).early(1/4),
|
||||||
scaleTranspose(8).early(3/8)
|
scaleTranspose(8).early(3/8)
|
||||||
).edit(thru).tone(keys).bypass("<1 0>/16"),
|
).apply(thru).tone(keys).mask("<~ x>/16"),
|
||||||
"<C2 Bb1 Ab1 [G1 [G2 G1]]>/2".struct("[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2".fast(2)).edit(thru).tone(bass),
|
"<C2 Bb1 Ab1 [G1 [G2 G1]]>/2".struct("[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2".fast(2)).apply(thru).tone(bass),
|
||||||
"<Cm7 Bb7 Fm7 G7b13>/2".struct("~ [x@0.1 ~]".fast(2)).voicings().edit(thru).every(2, early(1/8)).tone(keys).bypass("<0@7 1>/8".early(1/4))
|
"<Cm7 Bb7 Fm7 G7b13>/2".struct("~ [x@0.1 ~]".fast(2)).voicings().apply(thru).every(2, early(1/8)).tone(keys).mask("<x@7 ~>/8".early(1/4))
|
||||||
)
|
)
|
||||||
return stack(
|
return stack(
|
||||||
drums.fast(2),
|
drums.fast(2),
|
||||||
|
|
@ -363,9 +328,9 @@ export const callcenterhero = `()=>{
|
||||||
const bass = fmsynth({...osc('sawtooth6'),...adsr(0.05,.6,0.8,0.1)}).chain(vol(0.6), out);
|
const bass = fmsynth({...osc('sawtooth6'),...adsr(0.05,.6,0.8,0.1)}).chain(vol(0.6), out);
|
||||||
const s = scale(slowcat('F3 minor', 'Ab3 major', 'Bb3 dorian', 'C4 phrygian dominant').slow(4));
|
const s = scale(slowcat('F3 minor', 'Ab3 major', 'Bb3 dorian', 'C4 phrygian dominant').slow(4));
|
||||||
return stack(
|
return stack(
|
||||||
"0 2".struct("<x ~> [x ~]").edit(s).scaleTranspose(stack(0,2)).tone(lead),
|
"0 2".struct("<x ~> [x ~]").apply(s).scaleTranspose(stack(0,2)).tone(lead),
|
||||||
"<6 7 9 7>".struct("[~ [x ~]*2]*2").edit(s).scaleTranspose("[0,2] [2,4]".fast(2).every(4,rev)).tone(lead),
|
"<6 7 9 7>".struct("[~ [x ~]*2]*2").apply(s).scaleTranspose("[0,2] [2,4]".fast(2).every(4,rev)).tone(lead),
|
||||||
"-14".struct("[~ x@0.8]*2".early(0.01)).edit(s).tone(bass),
|
"-14".struct("[~ x@0.8]*2".early(0.01)).apply(s).tone(bass),
|
||||||
"c2*2".tone(membrane().chain(vol(0.6), out)),
|
"c2*2".tone(membrane().chain(vol(0.6), out)),
|
||||||
"~ c2".tone(noise().chain(vol(0.2), out)),
|
"~ c2".tone(noise().chain(vol(0.2), out)),
|
||||||
"c4*4".tone(metal(adsr(0,.05,0)).chain(vol(0.03), out))
|
"c4*4".tone(metal(adsr(0,.05,0)).chain(vol(0.03), out))
|
||||||
|
|
@ -373,3 +338,91 @@ export const callcenterhero = `()=>{
|
||||||
.slow(120 / bpm)
|
.slow(120 / bpm)
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
export const primalEnemy = `()=>{
|
||||||
|
const f = fast("<1 <2 [4 8]>>");
|
||||||
|
return stack(
|
||||||
|
"c3,g3,c4".struct("[x ~]*2").apply(f).transpose("<0 <3 [5 [7 [9 [11 13]]]]>>"),
|
||||||
|
"c2 [c2 ~]*2".tone(synth(osc('sawtooth8')).chain(vol(0.8),out)),
|
||||||
|
"c1*2".tone(membrane().chain(vol(0.8),out))
|
||||||
|
).slow(1)
|
||||||
|
}`;
|
||||||
|
export const drums = `stack(
|
||||||
|
"c1*2".tone(membrane().chain(vol(0.8),out)),
|
||||||
|
"~ c3".tone(noise().chain(vol(0.8),out)),
|
||||||
|
"c3*4".transpose("[-24 0]*2").tone(metal(adsr(0,.015)).chain(vol(0.8),out))
|
||||||
|
)
|
||||||
|
`;
|
||||||
|
export const xylophoneCalling = `()=>{
|
||||||
|
const t = x=> x.scaleTranspose("<0 2 4 3>/4").transpose(-2)
|
||||||
|
const s = x => x.scale(slowcat('C3 minor pentatonic','G3 minor pentatonic').slow(4))
|
||||||
|
const delay = new FeedbackDelay(1/8, .6).chain(vol(0.1), out);
|
||||||
|
const chorus = new Chorus(1,2.5,0.5).start();
|
||||||
|
return stack(
|
||||||
|
// melody
|
||||||
|
"<<10 7> <8 3>>/4".struct("x*3").apply(s)
|
||||||
|
.scaleTranspose("<0 3 2> <1 4 3>")
|
||||||
|
.superimpose(scaleTranspose(2).early(1/8))
|
||||||
|
.apply(t).tone(polysynth().set({
|
||||||
|
...osc('triangle4'),
|
||||||
|
...adsr(0,.08,0)
|
||||||
|
}).chain(vol(0.2).connect(delay),chorus,out)).mask("<~@3 x>/16".early(1/8)),
|
||||||
|
// pad
|
||||||
|
"[1,3]/4".scale('G3 minor pentatonic').apply(t).tone(polysynth().set({
|
||||||
|
...osc('square2'),
|
||||||
|
...adsr(0.1,.4,0.8)
|
||||||
|
}).chain(vol(0.2),chorus,out)).mask("<~ x>/32"),
|
||||||
|
// xylophone
|
||||||
|
"c3,g3,c4".struct("<x*2 x>").fast("<1 <2!3 [4 8]>>").apply(s).scaleTranspose("<0 <1 [2 [3 <4 5>]]>>").apply(t).tone(polysynth().set({
|
||||||
|
...osc('sawtooth4'),
|
||||||
|
...adsr(0,.1,0)
|
||||||
|
}).chain(vol(0.4).connect(delay),out)).mask("<x@3 ~>/16".early(1/8)),
|
||||||
|
// bass
|
||||||
|
"c2 [c2 ~]*2".scale('C hirajoshi').apply(t).tone(synth({
|
||||||
|
...osc('sawtooth6'),
|
||||||
|
...adsr(0,.03,.4,.1)
|
||||||
|
}).chain(vol(0.4),out)),
|
||||||
|
// kick
|
||||||
|
"<c1!3 [c1 ~]*2>*2".tone(membrane().chain(vol(0.8),out)),
|
||||||
|
// snare
|
||||||
|
"~ <c3!7 [c3 c3*2]>".tone(noise().chain(vol(0.8),out)),
|
||||||
|
// hihat
|
||||||
|
"c3*4".transpose("[-24 0]*2").tone(metal(adsr(0,.02)).chain(vol(0.5).connect(delay),out))
|
||||||
|
).slow(1)
|
||||||
|
}`;
|
||||||
|
export const sowhatelse = `()=> {
|
||||||
|
// mixer
|
||||||
|
const mix = (key) => vol({
|
||||||
|
chords: .2,
|
||||||
|
lead: 0.8,
|
||||||
|
bass: .4,
|
||||||
|
snare: .95,
|
||||||
|
kick: .9,
|
||||||
|
hihat: .35,
|
||||||
|
}[key]||0);
|
||||||
|
const delay = new FeedbackDelay(1/6, .3).chain(vol(.7), out);
|
||||||
|
const delay2 = new FeedbackDelay(1/6, .2).chain(vol(.15), out);
|
||||||
|
const chorus = new Chorus(1,2.5,0.5).start();
|
||||||
|
// instruments
|
||||||
|
const instr = (instrument) => ({
|
||||||
|
organ: polysynth().set({...osc('sawtooth4'), ...adsr(.01,.2,0)}).chain(mix('chords').connect(delay),out),
|
||||||
|
lead: polysynth().set({...osc('triangle4'),...adsr(0.01,.05,0)}).chain(mix('lead').connect(delay2), out),
|
||||||
|
bass: polysynth().set({...osc('sawtooth8'),...adsr(.02,.05,.3,.2)}).chain(mix('bass'),lowpass(3000), out),
|
||||||
|
pad: polysynth().set({...osc('square2'),...adsr(0.1,.4,0.8)}).chain(vol(0.15),chorus,out),
|
||||||
|
hihat: metal(adsr(0, .02, 0)).chain(mix('hihat'), out),
|
||||||
|
snare: noise(adsr(0, .15, 0.01)).chain(mix('snare'), lowpass(5000), out),
|
||||||
|
kick: membrane().chain(mix('kick'), out)
|
||||||
|
}[instrument]);
|
||||||
|
// harmony
|
||||||
|
const t = transpose("<0 0 1 0>/8");
|
||||||
|
const sowhat = scaleTranspose("0,3,6,9,11");
|
||||||
|
// track
|
||||||
|
return stack(
|
||||||
|
"[<0 4 [3 [2 1]]>]/4".struct("[x]*3").mask("[~ x ~]").scale('D5 dorian').off(1/6, scaleTranspose(-7)).off(1/3, scaleTranspose(-5)).apply(t).tone(instr('lead')).mask("<~ ~ x x>/8"),
|
||||||
|
"<<e3 [~@2 a3]> <[d3 ~] [c3 f3] g3>>".scale('D dorian').apply(sowhat).apply(t).tone(instr('organ')).mask("<x x x ~>/8"),
|
||||||
|
"<[d2 [d2 ~]*3]!3 <a1*2 c2*3 [a1 e2]>>".apply(t).tone(instr('bass')),
|
||||||
|
"c1*6".tone(instr('hihat')),
|
||||||
|
"~ c3".tone(instr('snare')),
|
||||||
|
"<[c1@5 c1] <c1 [[c1@2 c1] ~] [c1 ~ c1] [c1!2 ~ c1!3]>>".tone(instr('kick')),
|
||||||
|
"[2,4]/4".scale('D dorian').apply(t).tone(instr('pad')).mask("<x x x ~>/8")
|
||||||
|
).fast(6/8)
|
||||||
|
}`;
|
||||||
|
|
|
||||||
2
docs/dist/useRepl.js
vendored
2
docs/dist/useRepl.js
vendored
|
|
@ -41,8 +41,6 @@ function useRepl({tune, defaultSynth, autolink = true, onEvent}) {
|
||||||
const pushLog = (message) => setLog((log2) => log2 + `${log2 ? "\n\n" : ""}${message}`);
|
const pushLog = (message) => setLog((log2) => log2 + `${log2 ? "\n\n" : ""}${message}`);
|
||||||
const logCycle = (_events, cycle2) => {
|
const logCycle = (_events, cycle2) => {
|
||||||
if (_events.length) {
|
if (_events.length) {
|
||||||
pushLog(`# cycle ${cycle2}
|
|
||||||
` + _events.map((e) => e.show()).join("\n"));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const cycle = useCycle({
|
const cycle = useCycle({
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1346,4 +1346,4 @@ span.CodeMirror-selectedtext { background: none; }
|
||||||
color: white !important;
|
color: white !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*# sourceMappingURL=index.a25424f4.css.map */
|
/*# sourceMappingURL=index.fd7d9b66.css.map */
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<link rel="icon" href="/tutorial/favicon.e3ab9dd9.ico">
|
<link rel="icon" href="/tutorial/favicon.e3ab9dd9.ico">
|
||||||
<link rel="stylesheet" type="text/css" href="/tutorial/index.a25424f4.css">
|
<link rel="stylesheet" type="text/css" href="/tutorial/index.fd7d9b66.css">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="description" content="Strudel REPL">
|
<meta name="description" content="Strudel REPL">
|
||||||
<title>Strudel Tutorial</title>
|
<title>Strudel Tutorial</title>
|
||||||
|
|
@ -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.c743025b.js" defer=""></script>
|
<script src="/tutorial/index.8834957f.js" defer=""></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue