Tonejs / Tone.js

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

Syncing a `Part` with the `Transport.bpm` #1148

Closed braebo closed 1 year ago

braebo commented 1 year ago

When a Part is generated at runtime, its tempo seems to be desynced from the Transport bpm (sounds like it's defaulting to 120?). I noticed there is no sync method on the Part.

Is there some way to sync a dynamically generated Part with the Transport?

For some more info on my use-case -- I'm loading Midi files at runtime, and they can be selected from a dropdown. They can then be armed / played in the transport. All tracks and their Midi Parts play nicely together when generated with my generatePart function:

generatePart(notes: Note[], length: number, octave = 0, transpose = 0) {
    const part = new Part((time, note) => {
        const frequency = Frequency(note.name)
            .transpose(octave * 12 + transpose)
            .toFrequency()
        this.track.instrument.node.triggerAttackRelease(frequency, note.duration, time, note.velocity)

        Draw.schedule(() => {
            this.events.note.next(note)
        }, time - Tau.lookAhead)
    }, notes)

    part.loopEnd = Time(length).quantize('1n')
    part.loop = true

    return part
}

But when a new Midi file is selected and regenerate a new Part, replacing the old one, it seems to start at the correct time (on transport start, at 0), but it plays at the wrong tempo (sounds like it could be 120bpm instead of 100bpm) while everything else is still playing at the correct tempo.

To clarify, the problem is -- restarting the Transport and each Part results in syncronised playback for all parts except for the regenerated one.

I'm wondering if I'm using the Part incorrectly? Perhaps there is a better way to approach this?

Any insight would be much appreciated 🙏 Thanks!

braebo commented 1 year ago

It turns out this is fixed by updating the midi header's tempo with midi.header.setTempo. I found it thanks to this old issue: https://github.com/Tonejs/Midi/issues/93