From 352d8659ec724da97d8837f1dc5104fe1022e353 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 23 Oct 2025 14:02:41 +0100 Subject: [PATCH] wip --- packages/core/cyclist.mjs | 2 +- packages/core/hap.mjs | 6 +++++- packages/osc/osc.mjs | 13 +++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/core/cyclist.mjs b/packages/core/cyclist.mjs index 59e410c53..f0a9db5fc 100644 --- a/packages/core/cyclist.mjs +++ b/packages/core/cyclist.mjs @@ -60,7 +60,7 @@ export class Cyclist { const haps = this.pattern.queryArc(begin, end, { _cps: this.cps, cyclist: 'cyclist' }); haps.forEach((hap) => { - if (hap.hasOnset()) { + if (hap.hasOnset() || hap.context.processParts) { const targetTime = (hap.whole.begin - this.num_cycles_at_cps_change) / this.cps + this.seconds_at_cps_change + latency; const duration = hap.duration / this.cps; diff --git a/packages/core/hap.mjs b/packages/core/hap.mjs index 5f820d644..a63bff9c7 100644 --- a/packages/core/hap.mjs +++ b/packages/core/hap.mjs @@ -16,7 +16,7 @@ export class Hap { then the whole will be returned as None, in which case the given value will have been sampled from the point halfway between the start and end of the 'part' timespan. - The context is to store a list of source code locations causing the event. + The context is to store metadata, including a list of source code locations causing the event. The word 'Event' is more or less a reserved word in javascript, hence this class is named called 'Hap'. @@ -161,6 +161,10 @@ export class Hap { return new Hap(this.whole, this.part, this.value, context); } + withContext(f) { + return new Hap(this.whole, this.part, this.value, f(this.context)); + } + ensureObjectValue() { /* if (isNote(hap.value)) { // supports primitive hap values that look like notes diff --git a/packages/osc/osc.mjs b/packages/osc/osc.mjs index fe0691522..52668d932 100644 --- a/packages/osc/osc.mjs +++ b/packages/osc/osc.mjs @@ -72,6 +72,18 @@ export async function oscTrigger(hap, currentTime, cps = 1, targetTime) { osc.send(bundle); } +export async function oscTrigger(hap, currentTime, cps = 1, targetTime) { + const osc = await connect(); + const controls = parseControlsFromHap(hap, cps); + const keyvals = Object.entries(controls).flat(); + + const ts = Math.round(collator.calculateTimestamp(currentTime, targetTime) * 1000); + const message = new OSC.Message('/dirt/play', ...keyvals); + const bundle = new OSC.Bundle([message], ts); + bundle.timestamp(ts); // workaround for https://github.com/adzialocha/osc-js/issues/60 + osc.send(bundle); +} + /** * * Sends each hap as an OSC message, which can be picked up by SuperCollider or any other OSC-enabled software. @@ -82,3 +94,4 @@ export async function oscTrigger(hap, currentTime, cps = 1, targetTime) { * @returns Pattern */ export const osc = register('osc', (pat) => pat.onTrigger(oscTrigger)); +export const superdirt = register('superdirt', (pat) => pat.withHap(hap => hap.withContext(c => {...c, processParts: true})).onTrigger(superdirtTrigger));