mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-22 13:13:10 -04:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 06463da7fb | |||
| 2a0e66a862 | |||
| 9c37725436 | |||
| 06f3696ab0 | |||
| a4c4c6025c |
@@ -140,3 +140,8 @@ registerWidget('_spectrum', (id, options = {}, pat) => {
|
|||||||
const ctx = getCanvasWidget(id, options).getContext('2d');
|
const ctx = getCanvasWidget(id, options).getContext('2d');
|
||||||
return pat.spectrum({ ...options, ctx, id });
|
return pat.spectrum({ ...options, ctx, id });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
registerWidget('_cyclecounter', (id, options = {}, pat) => {
|
||||||
|
const ctx = getCanvasWidget(id, options).getContext('2d');
|
||||||
|
return pat.cyclecounter({ ...options, ctx, id });
|
||||||
|
});
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ export class Cyclist {
|
|||||||
this.beforeStart = beforeStart;
|
this.beforeStart = beforeStart;
|
||||||
this.cps = 0.5;
|
this.cps = 0.5;
|
||||||
this.num_ticks_since_cps_change = 0;
|
this.num_ticks_since_cps_change = 0;
|
||||||
|
this.loopStart = 0;
|
||||||
|
this.loopLength = 0;
|
||||||
this.lastTick = 0; // absolute time when last tick (clock callback) happened
|
this.lastTick = 0; // absolute time when last tick (clock callback) happened
|
||||||
this.lastBegin = 0; // query begin of last tick
|
this.lastBegin = 0; // query begin of last tick
|
||||||
this.lastEnd = 0; // query end of last tick
|
this.lastEnd = 0; // query end of last tick
|
||||||
@@ -48,6 +50,10 @@ export class Cyclist {
|
|||||||
this.lastBegin = begin;
|
this.lastBegin = begin;
|
||||||
const end = this.num_cycles_at_cps_change + num_cycles_since_cps_change;
|
const end = this.num_cycles_at_cps_change + num_cycles_since_cps_change;
|
||||||
this.lastEnd = end;
|
this.lastEnd = end;
|
||||||
|
if (this.loopLength > 0 && this.lastEnd >= this.loopStart + this.loopLength) {
|
||||||
|
this.lastEnd = this.loopStart + (this.lastEnd % 1);
|
||||||
|
this.num_ticks_since_cps_change = 0;
|
||||||
|
}
|
||||||
this.lastTick = phase;
|
this.lastTick = phase;
|
||||||
|
|
||||||
if (phase < t) {
|
if (phase < t) {
|
||||||
@@ -116,7 +122,7 @@ export class Cyclist {
|
|||||||
stop() {
|
stop() {
|
||||||
logger('[cyclist] stop');
|
logger('[cyclist] stop');
|
||||||
this.clock.stop();
|
this.clock.stop();
|
||||||
this.lastEnd = 0;
|
this.lastEnd = this.loopStart;
|
||||||
this.setStarted(false);
|
this.setStarted(false);
|
||||||
}
|
}
|
||||||
async setPattern(pat, autostart = false) {
|
async setPattern(pat, autostart = false) {
|
||||||
@@ -132,6 +138,19 @@ export class Cyclist {
|
|||||||
this.cps = cps;
|
this.cps = cps;
|
||||||
this.num_ticks_since_cps_change = 0;
|
this.num_ticks_since_cps_change = 0;
|
||||||
}
|
}
|
||||||
|
setLoop(start = 0, length = 0) {
|
||||||
|
if (start >= 0 && length >= 0) {
|
||||||
|
start = Math.floor(start);
|
||||||
|
length = Math.floor(length);
|
||||||
|
|
||||||
|
if (start != this.loopStart || length != this.loopLength) {
|
||||||
|
this.loopStart = Math.floor(start);
|
||||||
|
this.loopLength = Math.floor(length);
|
||||||
|
this.lastEnd = this.loopStart + (this.lastEnd % 1);
|
||||||
|
this.num_ticks_since_cps_change = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
log(begin, end, haps) {
|
log(begin, end, haps) {
|
||||||
const onsets = haps.filter((h) => h.hasOnset());
|
const onsets = haps.filter((h) => h.hasOnset());
|
||||||
console.log(`${begin.toFixed(4)} - ${end.toFixed(4)} ${Array(onsets.length).fill('I').join('')}`);
|
console.log(`${begin.toFixed(4)} - ${end.toFixed(4)} ${Array(onsets.length).fill('I').join('')}`);
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ export function repl({
|
|||||||
const toggle = () => scheduler.toggle();
|
const toggle = () => scheduler.toggle();
|
||||||
const setCps = (cps) => scheduler.setCps(cps);
|
const setCps = (cps) => scheduler.setCps(cps);
|
||||||
const setCpm = (cpm) => scheduler.setCps(cpm / 60);
|
const setCpm = (cpm) => scheduler.setCps(cpm / 60);
|
||||||
|
const setLoop = (start, length) => scheduler.setLoop(start, length);
|
||||||
|
|
||||||
// TODO - not documented as jsdoc examples as the test framework doesn't simulate enough context for `each` and `all`..
|
// TODO - not documented as jsdoc examples as the test framework doesn't simulate enough context for `each` and `all`..
|
||||||
|
|
||||||
@@ -167,6 +168,8 @@ export function repl({
|
|||||||
setcps: setCps,
|
setcps: setCps,
|
||||||
setCpm,
|
setCpm,
|
||||||
setcpm: setCpm,
|
setcpm: setCpm,
|
||||||
|
setLoop,
|
||||||
|
setloop: setLoop,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { Pattern } from '@strudel/core';
|
||||||
|
|
||||||
|
Pattern.prototype.cyclecounter = function (options = {}) {
|
||||||
|
return this.onPaint((ctx, time, haps, drawTime) => {
|
||||||
|
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||||
|
|
||||||
|
ctx.font = options.font || '2em monospace';
|
||||||
|
ctx.fillStyle = options.color || 'red';
|
||||||
|
ctx.textBaseline = 'bottom';
|
||||||
|
ctx.textAlign = 'right';
|
||||||
|
|
||||||
|
const div = options.div || 1;
|
||||||
|
|
||||||
|
ctx.fillText('Cycle' + (div > 1 ? '/' + div : '') + ' ' + ((time / div) >> 0), ctx.canvas.width, ctx.canvas.height);
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -4,3 +4,4 @@ export * from './draw.mjs';
|
|||||||
export * from './pianoroll.mjs';
|
export * from './pianoroll.mjs';
|
||||||
export * from './spiral.mjs';
|
export * from './spiral.mjs';
|
||||||
export * from './pitchwheel.mjs';
|
export * from './pitchwheel.mjs';
|
||||||
|
export * from './cyclecounter.mjs';
|
||||||
|
|||||||
Reference in New Issue
Block a user