This commit is contained in:
Jade (Rose) Rowland 2024-04-06 17:07:54 -04:00
parent 4086df95b7
commit 8e4549d6d3
5 changed files with 15 additions and 9 deletions

View File

@ -46,6 +46,7 @@ const sendTick = (phase, duration, tick, time) => {
num_seconds_at_cps_change, num_seconds_at_cps_change,
num_seconds_since_cps_change, num_seconds_since_cps_change,
cycle, cycle,
phase,
}); });
num_ticks_since_cps_change++; num_ticks_since_cps_change++;
}; };

View File

@ -34,6 +34,7 @@ function safeEval(str, options = {}) {
str = `(async ()=>${str})()`; str = `(async ()=>${str})()`;
} }
const body = `"use strict";return (${str})`; const body = `"use strict";return (${str})`;
console.log(body);
return Function(body)(); return Function(body)();
} }
@ -48,5 +49,6 @@ export const evaluate = async (code, transpiler) => {
// if no transpiler is given, we expect a single instruction (!wrapExpression) // if no transpiler is given, we expect a single instruction (!wrapExpression)
const options = { wrapExpression: !!transpiler }; const options = { wrapExpression: !!transpiler };
let evaluated = await safeEval(code, options); let evaluated = await safeEval(code, options);
console.log(evaluated);
return { mode: 'javascript', pattern: evaluated, meta }; return { mode: 'javascript', pattern: evaluated, meta };
}; };

View File

@ -59,18 +59,19 @@ export class NeoCyclist {
end, end,
tickdeadline, tickdeadline,
cycle, cycle,
phase,
} = payload; } = payload;
this.cps = cps; this.cps = cps;
this.cycle = cycle; this.cycle = cycle;
setTimeReference(num_seconds_at_cps_change, num_seconds_since_cps_change, tickdeadline); setTimeReference(num_seconds_at_cps_change, num_seconds_since_cps_change, tickdeadline);
processHaps(begin, end, num_cycles_at_cps_change, num_seconds_at_cps_change); processHaps(begin, end, num_cycles_at_cps_change, num_seconds_at_cps_change, phase);
this.time_at_last_tick_message = this.getTime(); this.time_at_last_tick_message = this.getTime();
}; };
const processHaps = (begin, end, num_cycles_at_cps_change, seconds_at_cps_change) => { const processHaps = (begin, end, num_cycles_at_cps_change, seconds_at_cps_change, phase) => {
if (this.started === false) { if (this.started === false) {
return; return;
} }
@ -85,7 +86,8 @@ export class NeoCyclist {
this.latency + this.latency +
this.worker_time_dif; this.worker_time_dif;
const duration = hap.duration / this.cps; const duration = hap.duration / this.cps;
onTrigger?.(hap, 0, duration, this.cps, targetTime); const deadline = targetTime - phase;
onTrigger?.(hap, deadline, duration, this.cps, targetTime);
} }
}); });
}; };

View File

@ -112,17 +112,17 @@ Pattern.prototype.midi = function (output) {
logger(`Midi device disconnected! Available: ${getMidiDeviceNamesString(outputs)}`), logger(`Midi device disconnected! Available: ${getMidiDeviceNamesString(outputs)}`),
}); });
return this.onTrigger((time, hap, currentTime, cps) => { return this.onTrigger((time, hap, currentTime, cps, targetTime) => {
if (!WebMidi.enabled) { if (!WebMidi.enabled) {
console.log('not enabled'); console.log('not enabled');
return; return;
} }
const device = getDevice(output, WebMidi.outputs); const device = getDevice(output, WebMidi.outputs);
hap.ensureObjectValue(); hap.ensureObjectValue();
//magic number to get audio engine to line up, can probably be calculated somehow
const offset = (time - currentTime) * 1000; const latency = 0.03;
// passing a string with a +num into the webmidi api adds an offset to the current time https://webmidijs.org/api/classes/Output // passing a string with a +num into the webmidi api adds an offset to the current time https://webmidijs.org/api/classes/Output
const timeOffsetString = `+${offset}`; const timeOffsetString = `+${(targetTime - currentTime + latency) * 1000}`;
// destructure value // destructure value
let { note, nrpnn, nrpv, ccn, ccv, midichan = 1, midicmd, gain = 1, velocity = 0.9 } = hap.value; let { note, nrpnn, nrpv, ccn, ccv, midichan = 1, midicmd, gain = 1, velocity = 0.9 } = hap.value;
@ -130,7 +130,7 @@ Pattern.prototype.midi = function (output) {
velocity = gain * velocity; velocity = gain * velocity;
// note off messages will often a few ms arrive late, try to prevent glitching by subtracting from the duration length // note off messages will often a few ms arrive late, try to prevent glitching by subtracting from the duration length
const duration = Math.floor((hap.duration.valueOf() / cps) * 1000 - 10); const duration = (hap.duration.valueOf() / cps) * 1000 - 10;
if (note != null) { if (note != null) {
const midiNumber = typeof note === 'number' ? note : noteToMidi(note); const midiNumber = typeof note === 'number' ? note : noteToMidi(note);
const midiNote = new Note(midiNumber, { attack: velocity, duration }); const midiNote = new Note(midiNumber, { attack: velocity, duration });

View File

@ -17,8 +17,9 @@ const hap2value = (hap) => {
export const webaudioOutputTrigger = (t, hap, ct, cps) => superdough(hap2value(hap), t - ct, hap.duration / cps, cps); export const webaudioOutputTrigger = (t, hap, ct, cps) => superdough(hap2value(hap), t - ct, hap.duration / cps, cps);
// uses more precise, absolute t if available, see https://github.com/tidalcycles/strudel/pull/1004 // uses more precise, absolute t if available, see https://github.com/tidalcycles/strudel/pull/1004
export const webaudioOutput = (hap, deadline, hapDuration, cps, t) => export const webaudioOutput = (hap, deadline, hapDuration, cps, t) => {
superdough(hap2value(hap), t ? `=${t}` : deadline, hapDuration); superdough(hap2value(hap), t ? `=${t}` : deadline, hapDuration);
};
Pattern.prototype.webaudio = function () { Pattern.prototype.webaudio = function () {
return this.onTrigger(webaudioOutputTrigger); return this.onTrigger(webaudioOutputTrigger);