Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#420 Become JACK timebase master

open
nobody
audio (15)
1
2012-09-16
2010-09-21
Anonymous
No

There is even a prototype in src/sound/JackDriver.h for the needed callback, and it would probably look something like this:

JackDriver::jackTimebaseCallback(jack_transport_state_t state,
jack_nframes_t nframes,
jack_position_t pos,
int new_pos, void
arg)
{

Composition *comp = INSERT MAGIC HERE TO GET A POINTER TO THE COMPOSITION

timeT t = comp->getPosition();

comp->getMusicalTimeForAbsoluteTime(t, pos->bar, pos->beat,
                               int &fraction, int &remainder);
pos->tick           = fraction;
pos->ticks_per_beat = fraction + remainder;

TimeSignature ts   = comp->getTimeSignatureAt(t);
pos->beats_per_bar = ts->getNumerator();
pos->beat_type     = 1 << (6-ts->getDenominator()); // Ugly hack warning!
pos->beats_per_minute   = Composition::getTempoQpm(comp->getCurrentTempo());

pos->valid = JackPositionBBT; // + JackBBTFrameOffset when we get deeper into the details?

}

Of course I never got as far as feeding this to the compiler, the most crucial part is missing. So the C++ might be a bit off (not my strongest language) but I hope this saves some developer a few minutes if this gets implemented.

Discussion

  • Chris Cannam
    Chris Cannam
    2010-09-28

    It's not quite that simple, I'm afraid -- there are threading issues to consider.

    The JACK timebase callback is called from the JACK process thread, which is a real-time priority thread separate from the thread that the main GUI and engine runs in.

    This means that (1) most of the methods on classes like Composition cannot safely be called from this thread because they do non-real-time-safe work such as memory allocations; and in any case (2) most of them cannot safely be called from any thread other than the main one without locking protection because they are not thread-safe.

    Essentially we need to push the timing data to the process thread rather than pull it. Probably the GUI thread should push the series of time-tempo changes to the sequencer, with the mapping between real-time and musical time for each, and then the process thread should calculate based on the difference between its own real-time and that of the most recent time-tempo change. (The GUI cannot push "current time" to the process thread because it would always be somewhat ahead of real-time due to buffering.)