summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/ardour/ardour/diskstream.h1
-rw-r--r--libs/ardour/audio_diskstream.cc35
-rw-r--r--libs/ardour/diskstream.cc144
-rw-r--r--libs/ardour/export_channel.cc2
-rw-r--r--libs/ardour/session.cc6
-rw-r--r--libs/ardour/session_transport.cc30
6 files changed, 125 insertions, 93 deletions
diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h
index f5b4b6da0d..da6297e0fb 100644
--- a/libs/ardour/ardour/diskstream.h
+++ b/libs/ardour/ardour/diskstream.h
@@ -233,6 +233,7 @@ class Diskstream : public SessionObject
virtual void set_align_style_from_io() {}
virtual void setup_destructive_playlist () {}
virtual void use_destructive_playlist () {}
+ virtual void prepare_to_stop (framepos_t pos);
void calculate_record_range(OverlapType ot, sframes_t transport_frame, nframes_t nframes,
nframes_t& rec_nframes, nframes_t& rec_offset);
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 450bf5d789..c8cc1c9ebf 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -428,8 +428,6 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
int ret = -1;
nframes_t rec_offset = 0;
nframes_t rec_nframes = 0;
- bool nominally_recording;
- bool re = record_enabled ();
bool collect_playback = false;
playback_distance = 0;
@@ -440,8 +438,6 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
check_record_status (transport_frame, nframes, can_record);
- nominally_recording = (can_record && re);
-
if (nframes == 0) {
return 0;
}
@@ -468,27 +464,26 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
frame has left the punch range (which will cause the "can_record" argument to be false).
*/
- if (nominally_recording || (re && was_recording && _session.get_record_enabled() && _session.config.get_punch_out())) {
- // Safeguard against situations where process() goes haywire when autopunching and last_recordable_frame < first_recordable_frame
- if (last_recordable_frame < first_recordable_frame) {
- last_recordable_frame = max_frames;
- }
-
- OverlapType ot = coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes);
- calculate_record_range (ot, transport_frame, nframes, rec_nframes, rec_offset);
-
- if (rec_nframes && !was_recording) {
- capture_captured = 0;
- was_recording = true;
- }
- }
+ // Safeguard against situations where process() goes haywire when autopunching and last_recordable_frame < first_recordable_frame
+ if (last_recordable_frame < first_recordable_frame) {
+ last_recordable_frame = max_frames;
+ }
+
+ OverlapType ot = coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes);
+
+ calculate_record_range (ot, transport_frame, nframes, rec_nframes, rec_offset);
+
+ if (rec_nframes && !was_recording) {
+ capture_captured = 0;
+ was_recording = true;
+ }
if (can_record && !_last_capture_regions.empty()) {
_last_capture_regions.clear ();
}
- if (nominally_recording || rec_nframes) {
+ if (rec_nframes) {
uint32_t limit = _io->n_ports ().n_audio();
@@ -576,7 +571,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
adjust_capture_position = rec_nframes;
- } else if (nominally_recording) {
+ } else if (can_record && record_enabled()) {
/* can't do actual capture yet - waiting for latency effects to finish before we start*/
diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc
index 07a1217b7a..ab4bd71663 100644
--- a/libs/ardour/diskstream.cc
+++ b/libs/ardour/diskstream.cc
@@ -525,6 +525,7 @@ Diskstream::check_record_status (nframes_t transport_frame, nframes_t /*nframes*
const int transport_rolling = 0x4;
const int track_rec_enabled = 0x2;
const int global_rec_enabled = 0x1;
+ const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
/* merge together the 3 factors that affect record status, and compute
what has changed.
@@ -537,88 +538,101 @@ Diskstream::check_record_status (nframes_t transport_frame, nframes_t /*nframes*
if (possibly_recording == last_possibly_recording) {
return;
}
+ if (possibly_recording == fully_rec_enabled) {
- /* change state */
-
- /* if per-track or global rec-enable turned on while the other was already on, we've started recording */
-
- if (((change & track_rec_enabled) && record_enabled() && (!(change & global_rec_enabled) && can_record)) ||
- ((change & global_rec_enabled) && can_record && (!(change & track_rec_enabled) && record_enabled()))) {
-
- /* starting to record: compute first+last frames */
+ if (last_possibly_recording == fully_rec_enabled) {
+ return;
+ }
+ /* we transitioned to recording. lets see if its transport based or a punch */
+
first_recordable_frame = transport_frame + _capture_offset;
last_recordable_frame = max_frames;
capture_start_frame = transport_frame;
- if (!(last_possibly_recording & transport_rolling) && (possibly_recording & transport_rolling)) {
-
- /* was stopped, now rolling (and recording) */
+ if (change & transport_rolling) {
+ /* transport-change (started rolling) */
+
if (_alignment_style == ExistingMaterial) {
-
- first_recordable_frame += _session.worst_output_latency();
-
- DEBUG_TRACE (DEBUG::Latency, string_compose ("Offset rec from stop. Capture offset: %1 Worst O/P Latency: %2 Roll Delay: %3 First Recordable Frame: %4 Transport Frame: %5\n",
- _capture_offset, _session.worst_output_latency(), _roll_delay, first_recordable_frame, transport_frame));
- } else {
+
+ /* there are two delays happening:
+
+ 1) inbound, represented by _capture_offset
+ 2) outbound, represented by _session.worst_output_latency()
+
+ the first sample to record occurs when the larger of these
+ two has elapsed, since they occur in parallel.
+
+ since we've already added _capture_offset, just add the
+ difference if _session.worst_output_latency() is larger.
+ */
+
+ if (_capture_offset < _session.worst_output_latency()) {
+ first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
+ }
+ } else {
first_recordable_frame += _roll_delay;
- }
-
- } else {
+ }
+
+ } else {
- /* was rolling, but record state changed */
+ /* punch in */
if (_alignment_style == ExistingMaterial) {
- /* manual punch in happens at the correct transport frame
- because the user hit a button. but to get alignment correct
- we have to back up the position of the new region to the
- appropriate spot given the roll delay.
- */
-
-
- /* autopunch toggles recording at the precise
+ /* There are two kinds of punch:
+
+ manual punch in happens at the correct transport frame
+ because the user hit a button. but to get alignment correct
+ we have to back up the position of the new region to the
+ appropriate spot given the roll delay.
+
+ autopunch toggles recording at the precise
transport frame, and then the DS waits
to start recording for a time that depends
on the output latency.
- */
-
- first_recordable_frame += _session.worst_output_latency();
-
- DEBUG_TRACE (DEBUG::Latency, string_compose ("Punch in manual/auto. Capture offset: %1 Worst O/P Latency: %2 Roll Delay: %3 First Recordable Frame: %4 Transport Frame: %5\n",
- _capture_offset, _session.worst_output_latency(), _roll_delay, first_recordable_frame, transport_frame));
- } else {
-
- if (_session.config.get_punch_in()) {
- first_recordable_frame += _roll_delay;
- } else {
- capture_start_frame -= _roll_delay;
- }
- }
- }
-
- prepare_record_status(capture_start_frame);
+ XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
- } else if (!record_enabled() || !can_record) {
-
- /* stop recording */
+ */
- last_recordable_frame = transport_frame + _capture_offset;
+ if (_capture_offset < _session.worst_output_latency()) {
+ /* see comment in ExistingMaterial block above */
+ first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
+ }
- if (_alignment_style == ExistingMaterial) {
- last_recordable_frame += _session.worst_output_latency();
- } else {
- last_recordable_frame += _roll_delay;
- }
-
- //first_recordable_frame = max_frames;
-
- DEBUG_TRACE (DEBUG::Latency, string_compose ("Stop record - %6 | %7. Capture offset: %1 Worst O/P Latency: %2 Roll Delay: %3 First Recordable Frame: %4 Transport Frame: %5\n",
- _capture_offset, _session.worst_output_latency(), _roll_delay, first_recordable_frame, transport_frame,
- can_record, record_enabled()));
- }
+ } else {
+ capture_start_frame -= _roll_delay;
+ }
+ }
+
+ prepare_record_status (capture_start_frame);
+
+ } else {
+
+ if (last_possibly_recording == fully_rec_enabled) {
+
+ /* we were recording last time */
+
+ if (change & transport_rolling) {
+ /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop() */
+
+ } else {
+ /* punch out */
+
+ last_recordable_frame = transport_frame + _capture_offset;
+
+ if (_alignment_style == ExistingMaterial) {
+ if (_session.worst_output_latency() > _capture_offset) {
+ last_recordable_frame += (_session.worst_output_latency() - _capture_offset);
+ }
+ } else {
+ last_recordable_frame += _roll_delay;
+ }
+ }
+ }
+ }
last_possibly_recording = possibly_recording;
}
@@ -673,3 +687,9 @@ Diskstream::calculate_record_range(OverlapType ot, sframes_t transport_frame, nf
break;
}
}
+
+void
+Diskstream::prepare_to_stop (framepos_t pos)
+{
+ last_recordable_frame = pos + _capture_offset;
+}
diff --git a/libs/ardour/export_channel.cc b/libs/ardour/export_channel.cc
index a09e6e21b6..f94ee13257 100644
--- a/libs/ardour/export_channel.cc
+++ b/libs/ardour/export_channel.cc
@@ -45,7 +45,7 @@ PortExportChannel::read (Sample * data, nframes_t frames) const
for (PortSet::const_iterator it = ports.begin(); it != ports.end(); ++it) {
if (*it != 0) {
- Sample* port_buffer = (*it)->get_audio_buffer(frames, 0).data();
+ Sample* port_buffer = (*it)->get_audio_buffer(frames).data();
for (uint32_t i = 0; i < frames; ++i) {
data[i] += (float) port_buffer[i];
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 22d2fc8037..21ed454c29 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -28,11 +28,9 @@
#include <unistd.h>
#include <limits.h>
-
#include <glibmm/thread.h>
#include <glibmm/miscutils.h>
#include <glibmm/fileutils.h>
-#include <glibmm/thread.h>
#include "pbd/error.h"
#include "pbd/boost_debug.h"
@@ -1043,9 +1041,7 @@ Session::disable_record (bool rt_context, bool force)
void
Session::step_back_from_record ()
{
- /* XXX really atomic compare+swap here */
- if (g_atomic_int_get (&_record_status) == Recording) {
- g_atomic_int_set (&_record_status, Enabled);
+ if (g_atomic_int_compare_and_exchange (&_record_status, Recording, Enabled)) {
if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index e5b580e2ab..12dc1c3d3d 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -197,10 +197,17 @@ Session::realtime_stop (bool abort, bool clear_state)
/* move the transport position back to where the
request for a stop was noticed. we rolled
- past that point to pick up delayed input.
+ past that point to pick up delayed input (and/or to delick)
*/
- decrement_transport_position (_worst_output_latency);
+ if (_worst_output_latency > current_block_size) {
+ /* we rolled past the stop point to pick up data that had
+ not yet arrived. move back to where the stop occured.
+ */
+ decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
+ } else {
+ decrement_transport_position (current_block_size);
+ }
/* the duration change is not guaranteed to have happened, but is likely */
@@ -1011,9 +1018,13 @@ Session::stop_transport (bool abort, bool clear_state)
return;
}
- if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
- _worst_output_latency > current_block_size)
- {
+ if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
+
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
+ (*i)->prepare_to_stop (_transport_frame);
+ }
/* we need to capture the audio that has still not yet been received by the system
at the time the stop is requested, so we have to roll past that time.
@@ -1035,6 +1046,15 @@ Session::stop_transport (bool abort, bool clear_state)
if ((transport_sub_state & PendingDeclickOut) == 0) {
+
+ if (!(transport_sub_state & StopPendingCapture)) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
+ (*i)->prepare_to_stop (_transport_frame);
+ }
+ }
+
transport_sub_state |= PendingDeclickOut;
/* we'll be called again after the declick */
pending_abort = abort;