summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2019-11-14 21:15:30 +0100
committerRobin Gareus <robin@gareus.org>2019-11-14 21:15:30 +0100
commit6481437f0a7e46941a7e998c160f0fdb8337f84b (patch)
tree3da10d9a3c4a3440f89e01fa56b6a9f92c8cc59c
parent3e99856f76702be7c497255323c69df514fdea1e (diff)
LV2 extension for host's time-scale vari-speed
Ardour 6 internally always runs at speed 1.0 (or -1.0, or stopped 0.0). There is no vari-speed that scale "BPM" or "n_sample" time progression per cycle. Instead Ardour 6 vari-speed mechanism transparently re-samples I/O. So process-time is scaled only relative to wall-clock time. From a plugin's POV this is similar to "freewheeling": The plugin processes data as if the host plays at speed 1.0. While the host plays this data at a different rate. Some plugins may like to be informed about the host's actual playback rate. Currently this is mainly for the benefit of github.com/x42/repitch.lv2.git
-rw-r--r--libs/ardour/ardour/lv2_plugin.h1
-rw-r--r--libs/ardour/ardour/uri_map.h1
-rw-r--r--libs/ardour/lv2_plugin.cc15
-rw-r--r--libs/ardour/uri_map.cc1
4 files changed, 15 insertions, 3 deletions
diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h
index 7b8233ee5a..247b7b603a 100644
--- a/libs/ardour/ardour/lv2_plugin.h
+++ b/libs/ardour/ardour/lv2_plugin.h
@@ -207,6 +207,7 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
double _next_cycle_speed; ///< Expected start sample of next run cycle
double _next_cycle_beat; ///< Expected bar_beat of next run cycle
double _current_bpm;
+ double _prev_time_scale; ///< previous Port::speed_ratio
PBD::ID _insert_id;
std::string _plugin_state_dir;
uint32_t _bpm_control_port_index;
diff --git a/libs/ardour/ardour/uri_map.h b/libs/ardour/ardour/uri_map.h
index 6c0b3c8991..9134c6be44 100644
--- a/libs/ardour/ardour/uri_map.h
+++ b/libs/ardour/ardour/uri_map.h
@@ -81,6 +81,7 @@ public:
uint32_t time_beatsPerMinute;
uint32_t time_frame;
uint32_t time_speed;
+ uint32_t time_scale;
uint32_t patch_Get;
uint32_t patch_Set;
uint32_t patch_property;
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index 865c14d1d1..514496e788 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -449,6 +449,7 @@ LV2Plugin::init(const void* c_plugin, samplecnt_t rate)
_next_cycle_speed = 1.0;
_next_cycle_beat = 0.0;
_current_bpm = 0.0;
+ _prev_time_scale = 0.0;
_seq_size = _engine.raw_buffer_size(DataType::MIDI);
_state_version = 0;
_was_activated = false;
@@ -2574,6 +2575,7 @@ write_position(LV2_Atom_Forge* forge,
const TempoMetric& t,
Timecode::BBT_Time& bbt,
double speed,
+ double time_scale,
double bpm,
samplepos_t position,
samplecnt_t offset)
@@ -2600,6 +2602,8 @@ write_position(LV2_Atom_Forge* forge,
lv2_atom_forge_float(forge, t.meter().divisions_per_bar());
lv2_atom_forge_key(forge, urids.time_beatsPerMinute);
lv2_atom_forge_float(forge, bpm);
+ lv2_atom_forge_key(forge, urids.time_scale);
+ lv2_atom_forge_float(forge, time_scale);
#else
lv2_atom_forge_blank(forge, &frame, 1, urids.time_Position);
lv2_atom_forge_property_head(forge, urids.time_frame, 0);
@@ -2617,6 +2621,8 @@ write_position(LV2_Atom_Forge* forge,
lv2_atom_forge_float(forge, t.meter().divisions_per_bar());
lv2_atom_forge_property_head(forge, urids.time_beatsPerMinute, 0);
lv2_atom_forge_float(forge, bpm);
+ lv2_atom_forge_key(forge, urids.time_scale);
+ lv2_atom_forge_float(forge, time_scale);
#endif
LV2_Evbuf_Iterator end = lv2_evbuf_end(buf);
@@ -2725,6 +2731,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
if (valid && (flags & PORT_INPUT)) {
if ((flags & PORT_POSITION)) {
Timecode::BBT_Time bbt (tmap.bbt_at_sample (start));
+ double time_scale = Port::speed_ratio ();
double bpm = tmap.tempo_at_sample (start).note_types_per_minute();
double beatpos = (bbt.bars - 1) * tmetric.meter().divisions_per_bar()
+ (bbt.beats - 1)
@@ -2732,11 +2739,12 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
beatpos *= tmetric.meter().note_divisor() / 4.0;
if (start != _next_cycle_start ||
speed != _next_cycle_speed ||
+ time_scale != _prev_time_scale ||
rint (1000 * beatpos) != rint(1000 * _next_cycle_beat) ||
bpm != _current_bpm) {
// Transport or Tempo has changed, write position at cycle start
write_position(&_impl->forge, _ev_buffers[port_index],
- tmetric, bbt, speed, bpm, start, 0);
+ tmetric, bbt, speed, time_scale, bpm, start, 0);
}
}
@@ -2770,8 +2778,8 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
bbt = tmap.bbt_at_sample (metric->sample());
double bpm = tmap.tempo_at_sample (start/*XXX*/).note_types_per_minute();
write_position(&_impl->forge, _ev_buffers[port_index],
- tmetric, bbt, speed, bpm,
- metric->sample(),
+ tmetric, bbt, speed, Port::speed_ratio (),
+ bpm, metric->sample(),
metric->sample() - start);
++metric_i;
}
@@ -3035,6 +3043,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
// Update expected transport information for next cycle so we can detect changes
_next_cycle_speed = speed;
_next_cycle_start = end;
+ _prev_time_scale = Port::speed_ratio ();
{
/* keep track of lv2:timePosition like plugins can do.
diff --git a/libs/ardour/uri_map.cc b/libs/ardour/uri_map.cc
index 18c7a1ac95..51c94e42a3 100644
--- a/libs/ardour/uri_map.cc
+++ b/libs/ardour/uri_map.cc
@@ -59,6 +59,7 @@ URIMap::URIDs::init(URIMap& uri_map)
time_beatsPerMinute = uri_map.uri_to_id("http://lv2plug.in/ns/ext/time#beatsPerMinute");
time_frame = uri_map.uri_to_id("http://lv2plug.in/ns/ext/time#frame");
time_speed = uri_map.uri_to_id("http://lv2plug.in/ns/ext/time#speed");
+ time_scale = uri_map.uri_to_id("http://ardour.org/lv2/time#scale"); // XXX
patch_Get = uri_map.uri_to_id("http://lv2plug.in/ns/ext/patch#Get");
patch_Set = uri_map.uri_to_id("http://lv2plug.in/ns/ext/patch#Set");
patch_property = uri_map.uri_to_id("http://lv2plug.in/ns/ext/patch#property");