diff options
author | Robin Gareus <robin@gareus.org> | 2019-11-14 21:15:30 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2019-11-14 21:15:30 +0100 |
commit | 6481437f0a7e46941a7e998c160f0fdb8337f84b (patch) | |
tree | 3da10d9a3c4a3440f89e01fa56b6a9f92c8cc59c | |
parent | 3e99856f76702be7c497255323c69df514fdea1e (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.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/uri_map.h | 1 | ||||
-rw-r--r-- | libs/ardour/lv2_plugin.cc | 15 | ||||
-rw-r--r-- | libs/ardour/uri_map.cc | 1 |
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"); |