19 Dec
2002
19 Dec
'02
2:14 a.m.
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?)
- units: ticks/beat (int or float?)
- 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
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
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.
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)
We can either accept this, or rethink defining tempo/timebase on modifiable
beats.
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.
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 know that sending CUEPOINT and TRANSPORT_STATE to every plugin is probably
wasteful. It's that dang 'special' event that makes me gag...
Thoughts? Things I missed? I'm going to start codifying this, soon. Fill
in the gaps of things I missed.
Tim