diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2010-04-12 22:35:06 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2010-04-12 22:35:06 +0000 |
commit | 981c8906fb9d2fc5b2071018a22947a87f6bd5db (patch) | |
tree | 4a7735cfb7d9fc1e4d94c5e3856d76894065b735 /libs | |
parent | ac8c7e427fd778201297469fb6ce189142e29ffa (diff) |
alignment/capture/positioning changes ported from 2.X
git-svn-id: svn://localhost/ardour2/branches/3.0@6886 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ardour/ardour/diskstream.h | 1 | ||||
-rw-r--r-- | libs/ardour/audio_diskstream.cc | 35 | ||||
-rw-r--r-- | libs/ardour/diskstream.cc | 144 | ||||
-rw-r--r-- | libs/ardour/export_channel.cc | 2 | ||||
-rw-r--r-- | libs/ardour/session.cc | 6 | ||||
-rw-r--r-- | libs/ardour/session_transport.cc | 30 |
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; |