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

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] XAP Time/Transport - varispeed/shuttle
From: David Olofson (david_AT_olofson.net)
Date: Thu Dec 19 2002 - 17:05:53 EET


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 ---


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Thu Dec 19 2002 - 17:16:46 EET