Robin Gareus edited this page Feb 10, 2013 · 1 revision

Having just implemented seamless looping in ardour, I find myself
wanting a way to use this in conjunction with the jack
transport system. This has been touched upon in the past, so
here is my proposal for extension:

Reintroduce two new items into jack_position_t's padding space:

    jack_nframes_t         loop_start;                                                                    
    jack_nframes_t         loop_end;                                                                      

Introduce a new api call:


which will do exactly the same thing as jack_transport_start
except the state (after slow-sync procedure) will be JackTransportLooping
(already defined).

jack_transport_reposition() will be used as-is to set/modify the
loop boundaries, and proper slow-sync procedure is still used
whenever loop bounds change while JackTransportLooping.

The key element of the JackTransportLooping state is that jack
will wrap the frame position appropriately after the cycle containing
or ending on the loop_end. All clients who can handle the looping
state will already be aware of the loop boundary from their last
slow-sync at reposition/start and are expected to have already made
preparations for the seamless wraparound.

On the last cycle in a given loop, the starting frame will be correct,
but due to the loop_end, the effective transport frame after the
loop_end within the cycle will wrap to loop_start
-- all clients are expected to handle this intra-cycle mod-arithmetic
internally. Jack will apply the proper mod-math at the start
of the next cycle.

The only issue i foresee is with clients who support the jack
transport but do not know about the JackTransportLooping state.
Depending on their implementation, their results could be unpredictable.
If they are simple (fast-sync) clients, most likely they will just run
past the loop_end in the last cycle, only to be corrected at the
start of the next cycle. If they are slow-sync, well... they
could quite easily become confused, or they might ignore the
looping altogether.....

Anyway, as you can see, the jack-side implementation of this is
next to trivial. Most of the onus is upon the clients to make
jack-wide seamless looping a workable reality.

State transitions are as follows.

  • JackTransportStopped
    -> jack_transport_start_loop()
    ifloop bounds legal then normal sync
    operation follows.....

    • JackTransportStarting
    • JackTransportLooping

  • JackTransportLooping
    -> jack_transport_stop()

    • JackTransportStopped

  • JackTransportLooping
    -> jack_transport_reposition()
    loop bounds legal (start must be strictly less than end),
    normal sync operations follow:
    * JackTransportStarting
    * JackTransportLooping

  • JackTransportLooping
    -> jack_transport_reposition()
    but loop bounds are illegal (start must be strictly less than end).
    * JackTransportStopped

    [instead of stopping, we could also transition into rolling]

  • JackTransportLooping
    -> jack_transport_start()
    normal sync operations follow:
    * JackTransportStarting
    * JackTransportRolling

  • JackTransportRolling
    -> jack_transport_start_loop()
    if loop bounds are legal, normal sync operations follow:
    * JackTransportStarting
    * JackTransportLooping

This thanks to David's mail archives - even more discussion at