summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-01-17 20:43:55 +0100
committerRobin Gareus <robin@gareus.org>2017-01-17 20:43:55 +0100
commita6e02c0d71b67f3c571229c932dc20ee476df69b (patch)
treee92f501814d844e264164bfbb9fb0fbcad1f3a1e /libs/ardour
parentfcbed9c1dcb8490d35eeb274d8ef417c15ee7deb (diff)
Implement Count-In (before recording), fixed BPM, up to 2 bars
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/session.h1
-rw-r--r--libs/ardour/ardour/session_configuration_vars.h1
-rw-r--r--libs/ardour/session.cc1
-rw-r--r--libs/ardour/session_process.cc41
-rw-r--r--libs/ardour/session_transport.cc33
5 files changed, 77 insertions, 0 deletions
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index b62229a03c..f9172c5d6c 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -1898,6 +1898,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
void click (framepos_t start, framecnt_t nframes);
void run_click (framepos_t start, framecnt_t nframes);
void add_click (framepos_t pos, bool emphasis);
+ framecnt_t _count_in_samples;
std::vector<Route*> master_outs;
diff --git a/libs/ardour/ardour/session_configuration_vars.h b/libs/ardour/ardour/session_configuration_vars.h
index db789553cb..2f8d52b2b2 100644
--- a/libs/ardour/ardour/session_configuration_vars.h
+++ b/libs/ardour/ardour/session_configuration_vars.h
@@ -36,6 +36,7 @@ CONFIG_VARIABLE (bool, auto_return, "auto-return", false)
CONFIG_VARIABLE (bool, auto_input, "auto-input", true)
CONFIG_VARIABLE (bool, punch_in, "punch-in", false)
CONFIG_VARIABLE (bool, punch_out, "punch-out", false)
+CONFIG_VARIABLE (bool, count_in, "count-in", false)
CONFIG_VARIABLE (MonitorChoice, session_monitoring, "session-monitoring", MonitorAuto)
CONFIG_VARIABLE (bool, layered_record_mode, "layered-record-mode", false)
CONFIG_VARIABLE (uint32_t, subframes_per_frame, "subframes-per-frame", 100)
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index f16324dca8..34e4c52e9f 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -300,6 +300,7 @@ Session::Session (AudioEngine &eng,
, click_length (0)
, click_emphasis_length (0)
, _clicks_cleared (0)
+ , _count_in_samples (0)
, _play_range (false)
, _range_selection (-1,-1)
, _object_selection (-1,-1)
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index ad6ed1c16a..9be7007d19 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -314,6 +314,47 @@ Session::process_with_events (pframes_t nframes)
process_event (ev);
}
+ /* count in */
+ if (_transport_speed != 1.0 && _count_in_samples > 0) {
+ _count_in_samples = 0;
+ }
+
+ if (_count_in_samples > 0) {
+ framecnt_t ns = std::min ((framecnt_t)nframes, _count_in_samples);
+
+ no_roll (ns);
+ run_click (_transport_frame - _count_in_samples, ns);
+
+ _count_in_samples -= ns;
+ nframes -= ns;
+
+ /* process events.. */
+ if (!events.empty() && next_event != events.end()) {
+ SessionEvent* this_event = *next_event;
+ Events::iterator the_next_one = next_event;
+ ++the_next_one;
+
+ while (this_event && this_event->action_frame == _transport_frame) {
+ process_event (this_event);
+ if (the_next_one == events.end()) {
+ this_event = 0;
+ } else {
+ this_event = *the_next_one;
+ ++the_next_one;
+ }
+ }
+ set_next_event ();
+ }
+
+ check_declick_out ();
+
+ if (nframes == 0) {
+ return;
+ } else {
+ _engine.split_cycle (ns);
+ }
+ }
+
/* Decide on what to do with quarter-frame MTC during this cycle */
bool const was_sending_qf_mtc = _send_qf_mtc;
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 5f1384d292..a6d25f05ab 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -45,6 +45,7 @@
#include "ardour/scene_changer.h"
#include "ardour/session.h"
#include "ardour/slave.h"
+#include "ardour/tempo.h"
#include "ardour/operations.h"
#include "pbd/i18n.h"
@@ -1616,6 +1617,38 @@ Session::start_transport ()
if (!dynamic_cast<MTC_Slave*>(_slave)) {
send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
}
+
+ if (actively_recording() && click_data && config.get_count_in ()) {
+ /* calculate count-in duration (in audio samples)
+ * - use [fixed] tempo/meter at _transport_frame
+ * - calc duration of 1 bar + time-to-beat before or at transport_frame
+ */
+ const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
+ const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
+
+ double div = meter.divisions_per_bar ();
+ double pulses = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * div / 4.0;
+ double beats_left = fmod (pulses, div);
+
+ _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
+
+ double dt = _count_in_samples / div;
+ if (beats_left == 0) {
+ /* at bar boundary, count-in 2 bars before start. */
+ _count_in_samples *= 2;
+ } else {
+ /* beats left after full bar until roll position */
+ _count_in_samples += meter.frames_per_grid (tempo, _current_frame_rate) * beats_left;
+ }
+
+ int clickbeat = 0;
+ framepos_t cf = _transport_frame - _count_in_samples;
+ while (cf < _transport_frame) {
+ add_click (cf - _worst_track_latency, clickbeat == 0);
+ cf += dt;
+ clickbeat = fmod (clickbeat + 1, div);
+ }
+ }
}
DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));