osc timing now hopefully works everywhere

This commit is contained in:
Felix Roos 2022-04-02 22:41:04 +02:00
parent 0c726d835d
commit c8e9fe519f
3 changed files with 9 additions and 11 deletions

View File

@ -7,9 +7,12 @@ const latency = 0.1;
Pattern.prototype.osc = function () { Pattern.prototype.osc = function () {
return this._withEvent((event) => { return this._withEvent((event) => {
const onTrigger = (time, event, startedAt) => { const onTrigger = (time, event, currentTime) => {
// time should be audio time of onset
// currentTime should be current time of audio context (slightly before time)
const keyvals = Object.entries(event.value).flat(); const keyvals = Object.entries(event.value).flat();
const ts = Math.floor(startedAt + (time + latency) * 1000); const offset = (time - currentTime + latency) * 1000;
const ts = Math.floor(Date.now() + offset);
const message = new OSC.Message('/dirt/play', ...keyvals); const message = new OSC.Message('/dirt/play', ...keyvals);
const bundle = new OSC.Bundle([message], ts); const bundle = new OSC.Bundle([message], ts);
bundle.timestamp(ts); // workaround for https://github.com/adzialocha/osc-js/issues/60 bundle.timestamp(ts); // workaround for https://github.com/adzialocha/osc-js/issues/60

View File

@ -10,8 +10,6 @@ import { State, TimeSpan } from '@strudel.cycles/core';
ready?: boolean; // if false, query will not be called on change props ready?: boolean; // if false, query will not be called on change props
} */ } */
export let startedAt;
// function useCycle(props: UseCycleProps) { // function useCycle(props: UseCycleProps) {
function useCycle(props) { function useCycle(props) {
// onX must use useCallback! // onX must use useCallback!
@ -44,7 +42,7 @@ function useCycle(props) {
?.filter((event) => event.part.begin.equals(event.whole.begin)) ?.filter((event) => event.part.begin.equals(event.whole.begin))
.forEach((event) => { .forEach((event) => {
Tone.getTransport().schedule((time) => { Tone.getTransport().schedule((time) => {
onEvent(time, event, startedAt); onEvent(time, event, Tone.getContext().currentTime);
Tone.Draw.schedule(() => { Tone.Draw.schedule(() => {
// do drawing or DOM manipulation here // do drawing or DOM manipulation here
onDraw?.(time, event); onDraw?.(time, event);
@ -59,10 +57,7 @@ function useCycle(props) {
const start = async () => { const start = async () => {
setStarted(true); setStarted(true);
if (!startedAt) { await Tone.start();
await Tone.start();
startedAt = Date.now() - Tone.getContext().currentTime * 1000;
}
Tone.getTransport().start('+0.1'); Tone.getTransport().start('+0.1');
}; };
const stop = () => { const stop = () => {

View File

@ -27,7 +27,7 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw }) {
const cycle = useCycle({ const cycle = useCycle({
onDraw, onDraw,
onEvent: useCallback( onEvent: useCallback(
(time, event, startedAt) => { (time, event, currentTime) => {
try { try {
onEvent?.(event); onEvent?.(event);
const { onTrigger, velocity } = event.context; const { onTrigger, velocity } = event.context;
@ -41,7 +41,7 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw }) {
/* console.warn('no instrument chosen', event); /* console.warn('no instrument chosen', event);
throw new Error(`no instrument chosen for ${JSON.stringify(event)}`); */ throw new Error(`no instrument chosen for ${JSON.stringify(event)}`); */
} else { } else {
onTrigger(time, event, startedAt); onTrigger(time, event, currentTime);
} }
} catch (err) { } catch (err) {
console.warn(err); console.warn(err);