13
0

lots of stuff related to capture alignment. things appear to be working now, but require the right alignment setting, which doesn't persist correctly at present

git-svn-id: svn://localhost/ardour2/branches/3.0@9107 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2011-03-08 20:12:40 +00:00
parent 82c794db70
commit 34b9883537
13 changed files with 164 additions and 201 deletions

View File

@ -149,8 +149,6 @@ class AudioDiskstream : public Diskstream
CubicInterpolation interpolation;
XMLNode* deprecated_io_node;
protected:
friend class Session;

View File

@ -50,6 +50,7 @@ namespace PBD {
extern uint64_t AudioPlayback;
extern uint64_t Panning;
extern uint64_t LV2;
extern uint64_t CaptureAlignment;
}
}

View File

@ -122,8 +122,8 @@ class Diskstream : public SessionObject, public PublicDiskstream
static void set_disk_io_chunk_frames (framecnt_t n) { disk_io_chunk_frames = n; }
/* Stateful */
virtual XMLNode& get_state(void) = 0;
virtual int set_state(const XMLNode&, int version) = 0;
virtual XMLNode& get_state(void);
virtual int set_state(const XMLNode&, int version);
virtual void monitor_input (bool) {}
@ -304,6 +304,7 @@ class Diskstream : public SessionObject, public PublicDiskstream
PBD::ScopedConnection ic_connection;
Flag _flags;
XMLNode* deprecated_io_node;
void route_going_away ();
};

View File

@ -74,7 +74,6 @@ gain_t* AudioDiskstream::_gain_buffer = 0;
AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
: Diskstream(sess, name, flag)
, deprecated_io_node(NULL)
, channels (new ChannelList)
{
/* prevent any write sources from being created */
@ -86,7 +85,6 @@ AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream:
AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
: Diskstream(sess, node)
, deprecated_io_node(NULL)
, channels (new ChannelList)
{
in_set_state = true;
@ -132,8 +130,6 @@ AudioDiskstream::~AudioDiskstream ()
}
channels.flush ();
delete deprecated_io_node;
}
void
@ -1491,7 +1487,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
RegionFactory::region_name (region_name, whole_file_region_name, false);
// cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add region " << region_name << endl;
cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add region " << region_name << endl;
try {
@ -1723,25 +1719,14 @@ AudioDiskstream::disengage_record_enable ()
XMLNode&
AudioDiskstream::get_state ()
{
XMLNode* node = new XMLNode ("Diskstream");
XMLNode& node (Diskstream::get_state());
char buf[64] = "";
LocaleGuard lg (X_("POSIX"));
boost::shared_ptr<ChannelList> c = channels.reader();
node->add_property ("flags", enum_2_string (_flags));
snprintf (buf, sizeof(buf), "%zd", c->size());
node->add_property ("channels", buf);
node->add_property ("playlist", _playlist->name());
snprintf (buf, sizeof(buf), "%.12g", _visible_speed);
node->add_property ("speed", buf);
node->add_property("name", _name);
id().print (buf, sizeof (buf));
node->add_property("id", buf);
node.add_property ("channels", buf);
if (!capturing_sources.empty() && _session.get_record_enabled()) {
XMLNode* cs_child = new XMLNode (X_("CapturingSources"));
@ -1764,18 +1749,14 @@ AudioDiskstream::get_state ()
}
cs_child->add_property (X_("at"), buf);
node->add_child_nocopy (*cs_child);
node.add_child_nocopy (*cs_child);
}
if (_extra_xml) {
node->add_child_copy (*_extra_xml);
}
return* node;
return node;
}
int
AudioDiskstream::set_state (const XMLNode& node, int /*version*/)
AudioDiskstream::set_state (const XMLNode& node, int version)
{
const XMLProperty* prop;
XMLNodeList nlist = node.children();
@ -1784,6 +1765,8 @@ AudioDiskstream::set_state (const XMLNode& node, int /*version*/)
XMLNode* capture_pending_node = 0;
LocaleGuard lg (X_("POSIX"));
/* prevent write sources from being created */
in_set_state = true;
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
@ -1796,27 +1779,9 @@ AudioDiskstream::set_state (const XMLNode& node, int /*version*/)
}
}
/* prevent write sources from being created */
in_set_state = true;
if ((prop = node.property ("name")) != 0) {
_name = prop->value();
}
if (deprecated_io_node) {
if ((prop = deprecated_io_node->property ("id")) != 0) {
_id = prop->value ();
}
} else {
if ((prop = node.property ("id")) != 0) {
_id = prop->value ();
}
}
if ((prop = node.property ("flags")) != 0) {
_flags = Flag (string_2_enum (prop->value(), _flags));
}
if (Diskstream::set_state (node, version)) {
return -1;
}
if ((prop = node.property ("channels")) != 0) {
nchans = atoi (prop->value().c_str());
@ -1837,38 +1802,15 @@ AudioDiskstream::set_state (const XMLNode& node, int /*version*/)
remove_channel (_n_channels.n_audio() - nchans);
}
if ((prop = node.property ("playlist")) == 0) {
return -1;
}
{
bool had_playlist = (_playlist != 0);
if (find_and_use_playlist (prop->value())) {
return -1;
}
if (!had_playlist) {
_playlist->set_orig_diskstream_id (id());
}
if (!destructive() && capture_pending_node) {
/* destructive streams have one and only one source per channel,
and so they never end up in pending capture in any useful
sense.
*/
use_pending_capture_data (*capture_pending_node);
}
}
if ((prop = node.property ("speed")) != 0) {
double sp = atof (prop->value().c_str());
if (realtime_set_speed (sp, false)) {
non_realtime_set_speed ();
}
}
if (!destructive() && capture_pending_node) {
/* destructive streams have one and only one source per channel,
and so they never end up in pending capture in any useful
sense.
*/
use_pending_capture_data (*capture_pending_node);
}
in_set_state = false;

View File

@ -47,4 +47,5 @@ uint64_t PBD::DEBUG::Solo = PBD::new_debug_bit ("solo");
uint64_t PBD::DEBUG::AudioPlayback = PBD::new_debug_bit ("audioplayback");
uint64_t PBD::DEBUG::Panning = PBD::new_debug_bit ("panning");
uint64_t PBD::DEBUG::LV2 = PBD::new_debug_bit ("lv2");
uint64_t PBD::DEBUG::CaptureAlignment = PBD::new_debug_bit ("capturealignment");

View File

@ -113,7 +113,7 @@ Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
, _persistent_alignment_style (ExistingMaterial)
, first_input_change (true)
, _flags (flag)
, deprecated_io_node (0)
{
}
@ -157,6 +157,7 @@ Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/)
, _persistent_alignment_style (ExistingMaterial)
, first_input_change (true)
, _flags (Recordable)
, deprecated_io_node (0)
{
}
@ -167,6 +168,8 @@ Diskstream::~Diskstream ()
if (_playlist) {
_playlist->release ();
}
delete deprecated_io_node;
}
void
@ -264,6 +267,7 @@ Diskstream::set_capture_offset ()
}
_capture_offset = _io->latency();
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: using IO latency, capture offset set to %2\n", name(), _capture_offset));
}
void
@ -434,6 +438,78 @@ Diskstream::set_name (const string& str)
return true;
}
XMLNode&
Diskstream::get_state ()
{
XMLNode* node = new XMLNode ("Diskstream");
char buf[64];
LocaleGuard lg (X_("POSIX"));
node->add_property ("flags", enum_2_string (_flags));
node->add_property ("playlist", _playlist->name());
node->add_property("name", _name);
id().print (buf, sizeof (buf));
node->add_property("id", buf);
snprintf (buf, sizeof(buf), "%f", _visible_speed);
node->add_property ("speed", buf);
if (_extra_xml) {
node->add_child_copy (*_extra_xml);
}
return *node;
}
int
Diskstream::set_state (const XMLNode& node, int /*version*/)
{
const XMLProperty* prop;
if ((prop = node.property ("name")) != 0) {
_name = prop->value();
}
if (deprecated_io_node) {
if ((prop = deprecated_io_node->property ("id")) != 0) {
_id = prop->value ();
}
} else {
if ((prop = node.property ("id")) != 0) {
_id = prop->value ();
}
}
if ((prop = node.property ("flags")) != 0) {
_flags = Flag (string_2_enum (prop->value(), _flags));
}
if ((prop = node.property ("playlist")) == 0) {
return -1;
}
{
bool had_playlist = (_playlist != 0);
if (find_and_use_playlist (prop->value())) {
return -1;
}
if (!had_playlist) {
_playlist->set_orig_diskstream_id (id());
}
}
if ((prop = node.property ("speed")) != 0) {
double sp = atof (prop->value().c_str());
if (realtime_set_speed (sp, false)) {
non_realtime_set_speed ();
}
}
return 0;
}
void
Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames, bool from_undo)
{
@ -545,29 +621,33 @@ Diskstream::check_record_status (framepos_t transport_frame, bool can_record)
last_recordable_frame = max_framepos;
capture_start_frame = transport_frame;
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: @ %7 basic FRF = %2 LRF = %3 CSF = %4 CO = %5, WLO = %6\n",
name(), first_recordable_frame, last_recordable_frame, capture_start_frame,
_capture_offset,
_session.worst_output_latency(),
transport_frame));
if (change & transport_rolling) {
/* transport-change (started rolling) */
if (_alignment_style == ExistingMaterial) {
/* 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.
/* audio played by ardour will take (up to) _session.worst_output_latency() ("WOL") to
appear at the speakers; audio played at the time when it does appear at
the speakers will take _capture_offset to arrive back here. we've
already added _capture_offset, so now add WOL.
*/
if (_capture_offset < _session.worst_output_latency()) {
first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
}
first_recordable_frame += _session.worst_output_latency();
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tROLL: shift FRF by delta between WOL %1\n",
first_recordable_frame));
} else {
first_recordable_frame += _roll_delay;
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tROLL: shift FRF by roll delay of %1 to %2\n",
_roll_delay, first_recordable_frame));
}
} else {
@ -576,29 +656,14 @@ Diskstream::check_record_status (framepos_t transport_frame, bool can_record)
if (_alignment_style == ExistingMaterial) {
/* 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.
XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
*/
if (_capture_offset < _session.worst_output_latency()) {
/* see comment in ExistingMaterial block above */
first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
}
/* see comment in ExistingMaterial block above */
first_recordable_frame += _session.worst_output_latency();
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tMANUAL PUNCH: shift FRF by delta between WOL and CO to %1\n",
first_recordable_frame));
} else {
capture_start_frame -= _roll_delay;
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tPUNCH: shift CSF by roll delay of %1 to %2\n",
_roll_delay, capture_start_frame));
}
}
@ -619,9 +684,7 @@ Diskstream::check_record_status (framepos_t transport_frame, bool can_record)
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);
}
last_recordable_frame += _session.worst_input_latency();
} else {
last_recordable_frame += _roll_delay;
}

View File

@ -34,6 +34,7 @@
#include "ardour/audioengine.h"
#include "ardour/buffer.h"
#include "ardour/debug.h"
#include "ardour/io.h"
#include "ardour/route.h"
#include "ardour/port.h"
@ -1158,6 +1159,8 @@ IO::latency () const
}
}
DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: max latency from %2 ports = %3\n",
name(), _ports.num_ports(), max_latency));
return max_latency;
}

View File

@ -1206,26 +1206,13 @@ MidiDiskstream::disengage_record_enable ()
XMLNode&
MidiDiskstream::get_state ()
{
XMLNode* node = new XMLNode ("Diskstream");
XMLNode& node (Diskstream::get_state());
char buf[64];
LocaleGuard lg (X_("POSIX"));
snprintf (buf, sizeof(buf), "0x%x", _flags);
node->add_property ("flags", buf);
node->add_property("channel-mode", enum_2_string(get_channel_mode()));
node.add_property("channel-mode", enum_2_string(get_channel_mode()));
snprintf (buf, sizeof(buf), "0x%x", get_channel_mask());
node->add_property("channel-mask", buf);
node->add_property ("playlist", _playlist->name());
snprintf (buf, sizeof(buf), "%f", _visible_speed);
node->add_property ("speed", buf);
node->add_property("name", _name);
id().print(buf, sizeof(buf));
node->add_property("id", buf);
node.add_property("channel-mask", buf);
if (_write_source && _session.get_record_enabled()) {
@ -1247,18 +1234,14 @@ MidiDiskstream::get_state ()
}
cs_child->add_property (X_("at"), buf);
node->add_child_nocopy (*cs_child);
node.add_child_nocopy (*cs_child);
}
if (_extra_xml) {
node->add_child_copy (*_extra_xml);
}
return* node;
return node;
}
int
MidiDiskstream::set_state (const XMLNode& node, int /*version*/)
MidiDiskstream::set_state (const XMLNode& node, int version)
{
const XMLProperty* prop;
XMLNodeList nlist = node.children();
@ -1266,12 +1249,11 @@ MidiDiskstream::set_state (const XMLNode& node, int /*version*/)
XMLNode* capture_pending_node = 0;
LocaleGuard lg (X_("POSIX"));
/* prevent write sources from being created */
in_set_state = true;
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
/*if ((*niter)->name() == IO::state_node_name) {
deprecated_io_node = new XMLNode (**niter);
}*/
assert ((*niter)->name() != IO::state_node_name);
if ((*niter)->name() == X_("CapturingSources")) {
@ -1279,21 +1261,9 @@ MidiDiskstream::set_state (const XMLNode& node, int /*version*/)
}
}
/* prevent write sources from being created */
in_set_state = true;
if ((prop = node.property ("name")) != 0) {
_name = prop->value();
}
if ((prop = node.property ("id")) != 0) {
_id = prop->value ();
}
if ((prop = node.property ("flags")) != 0) {
_flags = Flag (string_2_enum (prop->value(), _flags));
}
if (Diskstream::set_state (node, version)) {
return -1;
}
ChannelMode channel_mode = AllChannels;
if ((prop = node.property ("channel-mode")) != 0) {
@ -1308,36 +1278,12 @@ MidiDiskstream::set_state (const XMLNode& node, int /*version*/)
}
}
set_channel_mode(channel_mode, channel_mask);
if ((prop = node.property ("playlist")) == 0) {
return -1;
}
if (capture_pending_node) {
use_pending_capture_data (*capture_pending_node);
}
{
bool had_playlist = (_playlist != 0);
if (find_and_use_playlist (prop->value())) {
return -1;
}
if (!had_playlist) {
_playlist->set_orig_diskstream_id (id());
}
if (capture_pending_node) {
use_pending_capture_data (*capture_pending_node);
}
}
if ((prop = node.property ("speed")) != 0) {
double sp = atof (prop->value().c_str());
if (realtime_set_speed (sp, false)) {
non_realtime_set_speed ();
}
}
set_channel_mode (channel_mode, channel_mask);
in_set_state = false;

View File

@ -310,7 +310,13 @@ Port::total_latency () const
return jack_port_get_total_latency (jack, _jack_port);
#else
return 0;
jack_latency_range_t r;
jack_port_get_latency_range (_jack_port,
sends_output() ? JackPlaybackLatency : JackCaptureLatency,
&r);
DEBUG_TRACE (DEBUG::Latency, string_compose ("PORT %1: latency range %2 .. %3\n",
name(), r.min, r.max));
return r.max;
#endif
}

View File

@ -3051,7 +3051,7 @@ Route::update_total_latency ()
}
}
DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: internal redirect latency = %2\n", _name, own_latency));
DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: bus: internal redirect latency = %2\n", _name, own_latency));
_output->set_port_latency (own_latency);

View File

@ -328,6 +328,10 @@ Session::destroy ()
void
Session::set_worst_io_latencies ()
{
if (_state_of_the_state & InitialConnecting) {
return;
}
_worst_output_latency = 0;
_worst_input_latency = 0;
@ -341,6 +345,9 @@ Session::set_worst_io_latencies ()
_worst_output_latency = max (_worst_output_latency, (*i)->output()->latency());
_worst_input_latency = max (_worst_input_latency, (*i)->input()->latency());
}
DEBUG_TRACE (DEBUG::Latency, string_compose ("Worst output latency: %1 Worst input latency: %2\n",
_worst_output_latency, _worst_input_latency));
}
void
@ -429,8 +436,6 @@ Session::when_engine_running ()
BootMessage (_("Compute I/O Latencies"));
set_worst_io_latencies ();
if (_clicking) {
// XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
}
@ -644,7 +649,7 @@ Session::when_engine_running ()
}
}
/* catch up on send+insert cnts */
set_worst_io_latencies ();
_state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));

View File

@ -1508,7 +1508,7 @@ Session::update_latency_compensation (bool with_stop, bool abort)
_engine.update_total_latencies ();
}
DEBUG_TRACE(DEBUG::Latency, string_compose("worst case latency was %1\n", _worst_track_latency));
DEBUG_TRACE(DEBUG::Latency, string_compose("worst case route internal latency was %1\n", _worst_track_latency));
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
(*i)->set_latency_delay (_worst_track_latency);

View File

@ -97,10 +97,7 @@ Track::update_total_latency ()
}
}
#undef DEBUG_LATENCY
#ifdef DEBUG_LATENCY
cerr << _name << ": internal redirect (final) latency = " << own_latency << endl;
#endif
DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: track: internal redirect latency = %2\n", _name, own_latency));
_output->set_port_latency (own_latency);