summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorJesse Chappell <jesse@essej.net>2007-06-26 02:16:54 +0000
committerJesse Chappell <jesse@essej.net>2007-06-26 02:16:54 +0000
commite9b1b7110ba49103af8e99547c3a165526a80b14 (patch)
treef6eac5ae42f48605df6167bdc9a12421bdbe103b /libs
parentcdccec62fe0ec32c8f4ae1efd3d2ab70dae19dfc (diff)
* Added (let's call it revealed) ability to record while the transport is looping.
This works for both Internal (seamless) and JACK sync, new regions are created each cycle around the loop and stacked on top of each other. It is recommended for now that automatic crossfades be turned off when doing this. Punch-In/Out may be used also (this used to be the only way to accomplish recording while looping, but now the GUI represents it without goofiness. * Fixed the stuttering/stuck problem when looping with JACK sync * Fixed gui bug that prevented record-disable when latch record option is on * Fixed issue where it would rec-enable unnecessarily when passing through the punch-out point * Fixed corner case in diskstream record length (that no one would ever notice) git-svn-id: svn://localhost/ardour2/trunk@2035 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/audio_diskstream.h1
-rw-r--r--libs/ardour/ardour/diskstream.h1
-rw-r--r--libs/ardour/ardour/session.h1
-rw-r--r--libs/ardour/audio_diskstream.cc58
-rw-r--r--libs/ardour/session.cc21
-rw-r--r--libs/ardour/session_process.cc2
-rw-r--r--libs/ardour/session_transport.cc29
7 files changed, 95 insertions, 18 deletions
diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h
index 1bf94a4494..aaf5461361 100644
--- a/libs/ardour/ardour/audio_diskstream.h
+++ b/libs/ardour/ardour/audio_diskstream.h
@@ -227,6 +227,7 @@ class AudioDiskstream : public Diskstream
void finish_capture (bool rec_monitors_input, boost::shared_ptr<ChannelList>);
void transport_stopped (struct tm&, time_t, bool abort);
+ void transport_looped (nframes_t transport_frame);
void init (Diskstream::Flag);
diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h
index 3dd6555011..85fc3d3371 100644
--- a/libs/ardour/ardour/diskstream.h
+++ b/libs/ardour/ardour/diskstream.h
@@ -205,6 +205,7 @@ class Diskstream : public SessionObject
virtual void playlist_deleted (boost::weak_ptr<Playlist>);
virtual void transport_stopped (struct tm&, time_t, bool abort) = 0;
+ virtual void transport_looped (nframes_t transport_frame) = 0;
struct CaptureInfo {
uint32_t start;
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 1fea324406..f0a175c624 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -351,6 +351,7 @@ class Session : public PBD::StatefulDestructible
sigc::signal<void,nframes_t> PositionChanged; /* sent after any non-sequential motion */
sigc::signal<void> DurationChanged;
sigc::signal<void> HaltOnXrun;
+ sigc::signal<void> TransportLooped;
sigc::signal<void,RouteList&> RouteAdded;
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 7e583afeb7..d0e2b24263 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -465,7 +465,7 @@ AudioDiskstream::check_record_status (nframes_t transport_frame, nframes_t nfram
}
- if (_flags & Recordable) {
+ if (recordable() && destructive()) {
boost::shared_ptr<ChannelList> c = channels.reader();
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
@@ -594,7 +594,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
/* |--------| recrange
-------------- transrange
*/
- rec_nframes = last_recordable_frame - last_recordable_frame;
+ rec_nframes = last_recordable_frame - first_recordable_frame;
rec_offset = first_recordable_frame - transport_frame;
break;
}
@@ -1640,6 +1640,57 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
}
void
+AudioDiskstream::transport_looped (nframes_t transport_frame)
+{
+ if (was_recording) {
+ // all we need to do is finish this capture, with modified capture length
+ boost::shared_ptr<ChannelList> c = channels.reader();
+
+ // adjust the capture length knowing that the data will be recorded to disk
+ // only necessary after the first loop where we're recording
+ if (capture_info.size() == 0) {
+ capture_captured += _capture_offset;
+
+ if (_alignment_style == ExistingMaterial) {
+ capture_captured += _session.worst_output_latency();
+ } else {
+ capture_captured += _roll_delay;
+ }
+ }
+
+ finish_capture (true, c);
+
+ // the next region will start recording via the normal mechanism
+ // we'll set the start position to the current transport pos
+ // no latency adjustment or capture offset needs to be made, as that already happened the first time
+ capture_start_frame = transport_frame;
+ first_recordable_frame = transport_frame; // mild lie
+ last_recordable_frame = max_frames;
+ was_recording = true;
+
+ if (recordable() && destructive()) {
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
+
+ RingBufferNPT<CaptureTransition>::rw_vector transvec;
+ (*chan)->capture_transition_buf->get_write_vector(&transvec);
+
+ if (transvec.len[0] > 0) {
+ transvec.buf[0]->type = CaptureStart;
+ transvec.buf[0]->capture_val = capture_start_frame;
+ (*chan)->capture_transition_buf->increment_write_ptr(1);
+ }
+ else {
+ // bad!
+ fatal << X_("programming error: capture_transition_buf is full on rec loop! inconceivable!")
+ << endmsg;
+ }
+ }
+ }
+
+ }
+}
+
+void
AudioDiskstream::finish_capture (bool rec_monitors_input, boost::shared_ptr<ChannelList> c)
{
was_recording = false;
@@ -1654,7 +1705,6 @@ AudioDiskstream::finish_capture (bool rec_monitors_input, boost::shared_ptr<Chan
RingBufferNPT<CaptureTransition>::rw_vector transvec;
(*chan)->capture_transition_buf->get_write_vector(&transvec);
-
if (transvec.len[0] > 0) {
transvec.buf[0]->type = CaptureEnd;
transvec.buf[0]->capture_val = capture_captured;
@@ -2348,7 +2398,7 @@ AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t bufsize, nframes_t speed_si
playback_buf = new RingBufferNPT<Sample> (bufsize);
capture_buf = new RingBufferNPT<Sample> (bufsize);
- capture_transition_buf = new RingBufferNPT<CaptureTransition> (128);
+ capture_transition_buf = new RingBufferNPT<CaptureTransition> (256);
/* touch the ringbuffer buffers, which will cause
them to be mapped into locked physical RAM if
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 10860b0c88..6df71611ce 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -1120,7 +1120,7 @@ Session::disable_record (bool rt_context, bool force)
if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) {
- if (!Config->get_latched_record_enable () || force) {
+ if ((!Config->get_latched_record_enable () && !play_loop) || force) {
g_atomic_int_set (&_record_status, Disabled);
} else {
if (rs == Recording) {
@@ -1155,15 +1155,18 @@ Session::disable_record (bool rt_context, bool force)
void
Session::step_back_from_record ()
{
- g_atomic_int_set (&_record_status, Enabled);
+ /* XXX really atomic compare+swap here */
+ if (g_atomic_int_get (&_record_status) == Recording) {
+ g_atomic_int_set (&_record_status, Enabled);
- if (Config->get_monitoring_model() == HardwareMonitoring) {
- boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
-
- for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
- if (Config->get_auto_input() && (*i)->record_enabled ()) {
- //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
- (*i)->monitor_input (false);
+ if (Config->get_monitoring_model() == HardwareMonitoring) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
+ if (Config->get_auto_input() && (*i)->record_enabled ()) {
+ //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
+ (*i)->monitor_input (false);
+ }
}
}
}
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index 44ca7f1235..dc71a40ca2 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -489,7 +489,7 @@ Session::follow_slave (nframes_t nframes, nframes_t offset)
cerr << "delta = " << (int) (dir * this_delta)
<< " speed = " << slave_speed
<< " ts = " << _transport_speed
- << " M@"<< slave_transport_frame << " S@" << _transport_frame
+ << " M@ "<< slave_transport_frame << " S@ " << _transport_frame
<< " avgdelta = " << average_slave_delta
<< endl;
#endif
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 60cc8b91ae..7deb40c161 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -386,7 +386,8 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
_transport_frame = last_stop_frame;
- if (synced_to_jack()) {
+ if (synced_to_jack() && !play_loop) {
+ // cerr << "non-realtimestop: transport locate to " << _transport_frame << endl;
_engine.transport_locate (_transport_frame);
}
}
@@ -422,14 +423,16 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
/* XXX its a little odd that we're doing this here
when realtime_stop(), which has already executed,
will have done this.
+ JLC - so let's not because it seems unnecessary and breaks loop record
*/
-
+#if 0
if (!Config->get_latched_record_enable()) {
g_atomic_int_set (&_record_status, Disabled);
} else {
g_atomic_int_set (&_record_status, Enabled);
}
RecordStateChanged (); /* emit signal */
+#endif
}
if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
@@ -615,7 +618,7 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush,
void
Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
{
- if (actively_recording()) {
+ if (actively_recording() && !with_loop) {
return;
}
@@ -711,6 +714,22 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
// cancel looping directly, this is called from event handling context
set_play_loop (false);
}
+ else if (al && _transport_frame == al->start()) {
+ if (with_loop) {
+ // this is only necessary for seamless looping
+
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
+ if ((*i)->record_enabled ()) {
+ // tell it we've looped, so it can deal with the record state
+ (*i)->transport_looped(_transport_frame);
+ }
+ }
+ }
+
+ TransportLooped(); // EMIT SIGNAL
+ }
}
loop_changing = false;
@@ -893,7 +912,9 @@ Session::start_transport ()
break;
case Recording:
- disable_record (false);
+ if (!play_loop) {
+ disable_record (false);
+ }
break;
default: