[linux-audio-dev] XAP Time/Transport - varispeed/shuttle

David Olofson david at olofson.net
Thu Dec 19 10:12:01 UTC 2002


On Thursday 19 December 2002 07.09, Tim Hockin wrote:
> OK, so it's time for the Daily summary of points learned about time
> :)
>
> Here is the summary as it stands in my notes (so many notes!!)
>
>
> Time:
> ----
> SAMPLE_RATE:  all plugins know this from create()
>   - units: frames/sec (uint32)
>
> TEMPO:  a plugin can have a TEMPO control
>   - units: ticks/sec (float)
>   - deliver a TEMPO event at plugin init and whenever the tempo
> changes
>
> TIMEBASE:  (FIXME: instance-constant by host/user or a dynamic
> event?)

Constant for the sequencer at least, I think. (As to GUI level 
sequencing, it's usually fixed per song, and you have to do a 
destructive conversion of the file to change it. This is because the 
timestamps are usually integers, just like in MIDI files.)


> - units: ticks/beat (int or float?)

Integer value, at least. Actual format doesn't matter much, since you 
won't see many of these events. (That is, int->float conversion cost 
can be ignored.)


>   - let our docs suggest 1920 or 2520
>     - 2520 is divisible by 2,3,4,5,6,7,8,9,10,12,14,15,18,20 and
> more

Yeah. Could use any "magic" value. "Bigger is better", as long as the 
number itself doesn't take too many bits in the mantissa.


> METER:  a plugin can have a METER control (or controls)
>   - units: ticks/measure
>   - deliver a METER event at plugin init and whenever the meter
> changes

Yep. However, is it assumed that plugins should always count meter 
relative time from where the last METER event was received? I guess 
that would be the simplest and "safest" way, although it *does* 
reduce musical time accuracy to the sample accuracy level.

"So what?", you say; "We have only sample accurate timing anyway."

Yes - but the METER event is the *base* of your musical time 
calculations from the point you receive the event. That is, this 
rounding error adds up with the ones you get in your internal 
calculations. You could end up a sample off occasionally because of 
this.

So, it might be nice if we could squeeze in a field specifying more 
exactly when the meter actually starts. Think of it as the fraction 
bits of the event timestamp.


> TRANSPORT: a plugin can have a TRANSPORT control
>   - units: absolute ticks (double)
>   - deliver a TRANSPORT control when transport starts (start tick),
>     jumps (new tick value) and periodically (recommend each beat or
> each measure or 1/sec).  Reccommend to send on tempo/meter changes,
> too - special event TRANSPORT_CTL - parm = start/stop/freeze - do
> we really need a special event? see below...

I think we need a special event, since otherwise you can't move the 
transport position when the transport is stopped. (See my post on cue 
points.)


> In addition to the above, the host can enable:
>
> 	/* find out the timestamp of the next beat or bar */
> 	uint32_t next_beat = host->time_next(XAP_NEXT_BEAT);
> 	uint32_t next_bar = host->time_next(XAP_NEXT_BAR);
>
> 	/* get time info about a timestamp, assuming current tempo, etc */
> 	XAP_timeval times;
> 	int r = host->get_time(timestamp, &times,
> 	    XAP_TIME_TICKS | XAP_TIME_WALL | XAP_TIME_SMPTE);
> 	//FIXME: other time domains?
>
> 	/* find out what the transport is doing */
> 	XAP_transport trans = host->get_transport();


Provided the *host* knows anything about that. I think it's a rather 
serious restriction to assume that, since the rest is implicitly 
capable of handling timelines on a per-Channel basis.

I'd suggest doing the "host forwards callbacks to timeline manager" 
thing I proposed. That's just an integer argument for the calls 
above. Or we use a single pointer to a XAP_timeline struct, which 
contains the callback pointers above.


> In addition to all that, some sort of CUEPOINT mechanism as
> proposed to id loop-points, or simpler just a get_loops() method.

Maybe both. As mentioned before, they're not *exactly* the same thing.


> NOTE: with this dataset, changing the meter impacts the perceived
> tempo. Since we decided to say tempo is actual BEATS, and the value
> of beats can change, and ticks is dependant on beats:
>
> Rate = 48000 samples/sec
> Timebase = 100 ticks/beat
> Tempo = 120 beats/minute = 2 beats/sec = 200 ticks/sec
> Meter = 4/4 = 400 ticks/measure
> => a measure is 2 seconds (4 beats at 2 beats/sec)
>
> change Meter to 8/8
> => a measure is 4 seconds (8 beats at 2 beats per second)

Yes...


> We can either accept this, or rethink defining tempo/timebase on
> modifiable beats.

That would mean going back to assuming that QNs (or whatever) are 
special. If you're not using QNs as the beat value, why would you 
really want to specify the tempo as QNs/second or something? 
(Sequencers genarally do, but that's rather a UI + conventions issue. 
We're talking about the API now.)


> About special events and controls:
>
> I've voiced my dislike of general abuse of controls for this stuff.
>  In addition to it being a bit of an abuse of controls, we need to
> add a 'double' control type and we need to have a special event for
> TRANSPORT start/stop (and freeze if we do that).  ICK.

TEMPO is not special in any way, and nor is transport start/stop. 
Both *can* be normal controls. If they're not, they'll require 
special case handling in hosts for defaults and preset handling.


> What if we had plugin-global notifier events that told the plugin
> some things:

I don't like the idea of making them plugin global, but that's 
basically just a matter of how different from normal controls you 
want to make them.


>   TRANSPORT_STATE start/stop events
>   CUEPOINT add/remove
>   TIMEINFO - something time-ish has changed
>   TIMEBASE change
>   METER change
>   TEMPO change
>
> Some of those may actually be best left as controls (TEMPO, METER,
> TIMEBASE?).

Yes. (METER would be two controls.)


>  We could have a CUEPOINT control but it's getting
> ugly.

Yeah. Cue points are really N abstract objects, more like voices. 
Guess you could actually treat them as Voice Controls, but that would 
be abuse of the dimension of indexing that is voices. (There isn't 
one cue point per voice, but rather a bunch of them per timeline. 
That could be per Channel or per Plugin.)


> We could have special events for TRANSPORT start/stop but
> uggh.

No need. Just have "1" for rolling an "0" for stopped.


> Now I know that making some of this plugin-global means that
> different channels can't be on different timelines, but honestly, I
> don't think it matters :)

No, it's probably no big deal, but I'm not sure it really changes 
anything. Timeline generators and hosts still have to do hairy stuff 
to get it right, if it has anything to do with the host.

I simply don't like the idea of blindly assuming that the host *is* 
the sequencer. It doesn't eliminate any special cases anyway; the 
timeline stuff still needs some "nonstandard" interfaces to work.


> I know that sending CUEPOINT and TRANSPORT_STATE to every plugin is
> probably wasteful.  It's that dang 'special' event that makes me
> gag...

Well, I don't think we can do much about that. Some of them can be 
ordinary controls, but some special events are hard to avoid.

Either way, I think it's important to keep in mind that control != 
event. Events are just a transport layer for control data, and other 
stuff. Different datatypes already require different events. This 
applies to the timeline stuff as well, for the things that just don't 
fit in the normal datatypes.

Indeed, this means you get more datatypes to deal with - but how 
different is that from a bunch of extra calls in the host struct, 
really?


> Thoughts?  Things I missed?  I'm going to start codifying this,
> soon.  Fill in the gaps of things I missed.

I'll try to wrap my version up and release it, in case you want the 
event handling macros or something. They're adapted from Audiality, 
and should be fully functional. Still need a nice sort/merge 
implementation for N queues into 1, though. (I haven't used that in 
Audiality so far.)

No point in doing *everything* twice. :-)


//David Olofson - Programmer, Composer, Open Source Advocate

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -'
   --- http://olofson.net --- http://www.reologica.se ---



More information about the Linux-audio-dev mailing list