summaryrefslogtreecommitdiff
path: root/libs/ardour/session_process.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-09-28 06:31:12 +0200
committerRobin Gareus <robin@gareus.org>2017-09-29 05:03:48 +0200
commit8139becb1898187729b0ea57f145302d4975bf3a (patch)
tree79638d87c587765784fe56eeb530ff792442e0c5 /libs/ardour/session_process.cc
parent8ff3b5ecf6bd2b7d69b8f154ba8d21eb4fe86304 (diff)
Ongoing work on latency compensation
The general goal is to align transport-sample to be the audible frame and use that as "anchor" for all processing. transport_sample cannot become negative (00:00:00:00 is the first audible frame). Internally transport pre-rolls (read-ahead) before the transport starts to move. This allows inputs and disk to prefill the pipeline. When starting to roll, the session counts down a global "remaning preroll" counter, which is the worst-latency from in-to-out. Each route in turn will start processing at its own output-latency. Route::process_output_buffers() - which does the actual processing incl disk i/o - begins by offsetting the "current sample" by the route's process-latency and decrements the offset for each latent processor. At the end of the function the output will be aligned and match transport-sample - downstream-playback-latency (if any). PS. This commit is a first step only: transport looping & vari-speed have not yet been implemented/updated.
Diffstat (limited to 'libs/ardour/session_process.cc')
-rw-r--r--libs/ardour/session_process.cc41
1 files changed, 35 insertions, 6 deletions
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index 1674cd9a7a..ed5422cf07 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -292,18 +292,47 @@ Session::process_with_events (pframes_t nframes)
process_event (ev);
}
- /* count in */
+ /* only count-in when going to roll at speed 1.0 */
if (_transport_speed != 1.0 && _count_in_samples > 0) {
_count_in_samples = 0;
}
+ if (_transport_speed == 0.0) {
+ _remaining_latency_preroll = 0;
+ }
+
+ assert (_count_in_samples == 0 || _remaining_latency_preroll == 0 || _count_in_samples == _remaining_latency_preroll);
- if (_count_in_samples > 0) {
- samplecnt_t ns = std::min ((samplecnt_t)nframes, _count_in_samples);
+ if (_count_in_samples > 0 || _remaining_latency_preroll > 0) {
+ samplecnt_t ns;
+
+ if (_remaining_latency_preroll > 0) {
+ ns = std::min ((samplecnt_t)nframes, _remaining_latency_preroll);
+ } else {
+ ns = std::min ((samplecnt_t)nframes, _count_in_samples);
+ }
+
+ if (_count_in_samples > 0) {
+ run_click (_transport_sample - _count_in_samples, ns);
+ assert (_count_in_samples >= ns);
+ _count_in_samples -= ns;
+ }
- no_roll (ns);
- run_click (_transport_sample - _count_in_samples, ns);
+ if (_remaining_latency_preroll > 0) {
+ if (_count_in_samples == 0) {
+ click (_transport_sample - _remaining_latency_preroll, ns);
+ }
+ if (process_routes (ns, session_needs_butler)) {
+ fail_roll (ns);
+ }
+ } else {
+ no_roll (ns);
+ }
+
+ if (_remaining_latency_preroll > 0) {
+ assert (_remaining_latency_preroll >= ns);
+ _remaining_latency_preroll -= ns;
+ }
- _count_in_samples -= ns;
nframes -= ns;
/* process events.. */