mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-26 13:08:28 +00:00
log + drawLine
This commit is contained in:
parent
e747c0b060
commit
9e2e5ce581
24
packages/core/drawLine.mjs
Normal file
24
packages/core/drawLine.mjs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { gcd } from './fraction.mjs';
|
||||||
|
|
||||||
|
function drawLine(pat) {
|
||||||
|
let s = '';
|
||||||
|
let c = 0;
|
||||||
|
while (s.length < 60) {
|
||||||
|
const haps = pat.queryArc(c, c + 1);
|
||||||
|
const durations = haps.map((hap) => hap.duration);
|
||||||
|
const totalSlots = gcd(...durations).inverse();
|
||||||
|
haps.forEach((hap) => {
|
||||||
|
const duration = hap.whole.end.sub(hap.whole.begin);
|
||||||
|
const slots = totalSlots.mul(duration);
|
||||||
|
s += Array(slots.valueOf())
|
||||||
|
.fill()
|
||||||
|
.map((_, i) => (!i ? hap.value : '-'))
|
||||||
|
.join('');
|
||||||
|
});
|
||||||
|
s += '|';
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default drawLine;
|
||||||
@ -72,6 +72,12 @@ const fraction = (n) => {
|
|||||||
return Fraction(n);
|
return Fraction(n);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const gcd = (...fractions) => {
|
||||||
|
return fractions.reduce((gcd, fraction) => gcd.gcd(fraction), fraction(1));
|
||||||
|
};
|
||||||
|
|
||||||
|
fraction._original = Fraction;
|
||||||
|
|
||||||
export default fraction;
|
export default fraction;
|
||||||
|
|
||||||
// "If you concern performance, cache Fraction.js objects and pass arrays/objects.“
|
// "If you concern performance, cache Fraction.js objects and pass arrays/objects.“
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export class Hap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get duration() {
|
get duration() {
|
||||||
return this.whole.end.sub(this.whole.begin).valueOf();
|
return this.whole.end.sub(this.whole.begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
wholeOrPart() {
|
wholeOrPart() {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import Hap from './hap.mjs';
|
|||||||
import State from './state.mjs';
|
import State from './state.mjs';
|
||||||
|
|
||||||
import { isNote, toMidi, compose, removeUndefineds, flatten, id, listRange, curry, mod } from './util.mjs';
|
import { isNote, toMidi, compose, removeUndefineds, flatten, id, listRange, curry, mod } from './util.mjs';
|
||||||
|
import drawLine from './drawLine.mjs';
|
||||||
|
|
||||||
export class Pattern {
|
export class Pattern {
|
||||||
// the following functions will get patternFactories as nested functions:
|
// the following functions will get patternFactories as nested functions:
|
||||||
@ -563,6 +564,17 @@ export class Pattern {
|
|||||||
return this._withContext((context) => ({ ...context, color }));
|
return this._withContext((context) => ({ ...context, color }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log() {
|
||||||
|
return this._withEvent((e) => {
|
||||||
|
return e.setContext({ ...e.context, logs: (e.context?.logs || []).concat([e.show()]) });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
drawLine() {
|
||||||
|
console.log(drawLine(this));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
_segment(rate) {
|
_segment(rate) {
|
||||||
return this.struct(pure(true)._fast(rate));
|
return this.struct(pure(true)._fast(rate));
|
||||||
}
|
}
|
||||||
@ -803,7 +815,20 @@ Pattern.prototype.patternified = [
|
|||||||
'velocity',
|
'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 = { pure, stack, slowcat, fastcat, cat, timeCat, sequence, seq, polymeter, pm, polyrhythm, pr };
|
Pattern.prototype.factories = {
|
||||||
|
pure,
|
||||||
|
stack,
|
||||||
|
slowcat,
|
||||||
|
fastcat,
|
||||||
|
cat,
|
||||||
|
timeCat,
|
||||||
|
sequence,
|
||||||
|
seq,
|
||||||
|
polymeter,
|
||||||
|
pm,
|
||||||
|
polyrhythm,
|
||||||
|
pr,
|
||||||
|
};
|
||||||
// the magic happens in Pattern constructor. Keeping this in prototype enables adding methods from the outside (e.g. see tonal.ts)
|
// the magic happens in Pattern constructor. Keeping this in prototype enables adding methods from the outside (e.g. see tonal.ts)
|
||||||
|
|
||||||
// Elemental patterns
|
// Elemental patterns
|
||||||
|
|||||||
9
packages/core/test/fraction.test.mjs
Normal file
9
packages/core/test/fraction.test.mjs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import Fraction, { gcd } from '../fraction.mjs';
|
||||||
|
import { strict as assert } from 'assert';
|
||||||
|
|
||||||
|
describe('gcd', () => {
|
||||||
|
it('should work', () => {
|
||||||
|
const F = Fraction._original;
|
||||||
|
assert.equal(gcd(F(1 / 6), F(1 / 4)).toFraction(), '1/12');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -37,6 +37,9 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw }) {
|
|||||||
(time, event, currentTime) => {
|
(time, event, currentTime) => {
|
||||||
try {
|
try {
|
||||||
onEvent?.(event);
|
onEvent?.(event);
|
||||||
|
if (event.context.logs?.length) {
|
||||||
|
event.context.logs.forEach(pushLog);
|
||||||
|
}
|
||||||
const { onTrigger, velocity } = event.context;
|
const { onTrigger, velocity } = event.context;
|
||||||
if (!onTrigger) {
|
if (!onTrigger) {
|
||||||
if (defaultSynth) {
|
if (defaultSynth) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user