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?)
- units: ticks/beat (int or float?)
float. for all integer tempo/meter setups, we'll fit things with no
rounding into the 24 bits of a float, yet we'll still allow for other
things as well.
- 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
nice! i'll change ardour to use this value immediately.
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
i think that ticks/measure is a nice idea. combined with ticks/sec for
tempo, you can compute everything you need. however, i don't see how
you can derive the actual western A/B form from just this information,
and this might be necessary for some purposes.
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...
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, ×,
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();
In addition to all that, some sort of CUEPOINT mechanism as proposed to id
loop-points, or simpler just a get_loops() method.
i think that having multiple methods to ask about "current" time is a
mistake. i think that VST's approach is better: have a single function
that retrieves all the information (actually, in VST, you set a
bitfield to specify which information you want). the host doesn't
compute anything till the first call to the function (by a plugin),
thereafter, it uses the precomputed value of the struct that holds the
data. thus:
typedef struct __xap_timeinfo {
... somewhat like VST ...
} XAP_timeinfo;
XAP_timeinfo* time;
time = host->get_timeinfo(... possible bits ...);
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)
that seems entirely correct to me, but then i'm not a musician. when
i've asked my musician friends, i get two responses. the rock/pop
people are used to 1 beat = quarter note and tempo =
quarters-per-minute. the classical folks are more experienced with
tempo being denoted in beats-per-minute, and found the idea of it
being forced to be quarters-per-minute rather odd. so you'd have two
different responses to this. the classical people i know would find
this sensible; the rock/pop people might find it odd that the tempo
continues to be N of some unit, yet the apparent tempo has changed
(because they aren't used to the idea that the unit of tempo is a
beat, not a quarter note).
What if we had plugin-global notifier events that told
the plugin some
things:
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?). We could have a CUEPOINT control but it's getting ugly. We
could have special events for TRANSPORT start/stop but uggh.
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 :)
i would agree with this. i think its a very sensible idea.
--p