Tonejs / Tone.js

A Web Audio framework for making interactive music in the browser.
https://tonejs.github.io
MIT License
13.4k stars 976 forks source link

schedule() callback is passing through an unexpected time when invoked. #1048

Closed kodokoto closed 2 years ago

kodokoto commented 2 years ago

Hi there, I just want to start off by saying how amazing this framework is, and by thanking everyone who has contributed to it!

I am currently trying to schedule midi TempoEvents (generated from tonejs/Midi) on the Transport, and I found something unusual. When scheduling a BPM change at a specific time (in ticks), the time that gets passed through in the callback when it is invoked is not the same as the one given as an argument when the schedule was called.

I made a codepen that shows what I mean https://codepen.io/kodokoto/pen/yLPZrbZ?editors=1011

I don't know if this is a bug, or if it's working as intended. If the case is the latter, could I suggest giving schedule() an optional value parameter that takes in an object with a time property.

It would be incredibly useful for scheduling any automation and it would work in exactly the same way as the part() constructor. i.e like this:

for (tempoEvent of midi.header.tempos)
{
    Tone.Transport.schedule(((time, value) => {
        Tone.Transport.bpm.value = value.bpm;
    }), tempoEvent);
}

I think it would be a good feature to add, if you agree I would be willing to make the PR.

tambien commented 2 years ago

This is a confusing part of the Transport because there are really two clocks at play in scheduling. There's the transport clock which can be started and stopped and there is the audio context time which increments upward from 0 when it's started.

The time property passed into the callback for scheduling is in AudioContext time so i wouldn't expect it to match up to the transport time when converted with Tone.TransportTime(time). The time parameter for that class expect a time relative to the start of the Transport.

I believe what you're looking for is: Transport.getTicksAtTime which will convert the AudioContext time to Transport ticks.

kodokoto commented 2 years ago

Thank you for the speedy reply, that certainly fixed my issue!