work to make destructive recording actually do something vaguely close to correct
authorPaul Davis <paul@linuxaudiosystems.com>
Mon, 30 Jan 2006 14:10:37 +0000 (14:10 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 30 Jan 2006 14:10:37 +0000 (14:10 +0000)
git-svn-id: svn://localhost/trunk/ardour2@305 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/destructive_filesource.h
libs/ardour/ardour/filesource.h
libs/ardour/destructive_filesource.cc
libs/ardour/diskstream.cc
libs/ardour/session.cc
libs/gtkmm2ext/gtk_ui.cc

index 0663d7f0346a23e0fdc3fac30ee2a5732b934215..bb46fdfd222a6e6a6d7ce4aa43630084411573bc 100644 (file)
@@ -36,7 +36,8 @@ class DestructiveFileSource : public FileSource {
        ~DestructiveFileSource ();
 
        int  seek (jack_nframes_t frame);
-       void mark_capture_start ();
+       jack_nframes_t last_capture_start_frame() const;
+       void mark_capture_start (jack_nframes_t);
        void mark_capture_end ();
        void clear_capture_marks();
 
@@ -50,6 +51,7 @@ class DestructiveFileSource : public FileSource {
 
        bool          _capture_start;
        bool          _capture_end;
+       jack_nframes_t capture_start_frame;
        jack_nframes_t file_pos;
        Sample*        xfade_buf;
 
index fc86656c2ed8a73fe924f35edac86f8f7e4954de..e4261590145e3095e749a62894ef0b988ccda3c3 100644 (file)
@@ -56,6 +56,12 @@ class FileSource : public Source {
        string         old_peak_path(string audio_path);
        string         path() const { return _path; }
 
+       virtual int            seek (jack_nframes_t frame) {return 0; }
+       virtual jack_nframes_t last_capture_start_frame() const { return 0; }
+       virtual void           mark_capture_start (jack_nframes_t) {}
+       virtual void           mark_capture_end () {}
+       virtual void           clear_capture_marks() {}
+
        int update_header (jack_nframes_t when, struct tm&, time_t);
 
        int move_to_trash (const string trash_dir_name);
index 186166e08ce24517bbf3f946d1a3034201b082dd..6df6ff06afcc3306b4cf2263d1e7e6e1a1b401d4 100644 (file)
@@ -52,6 +52,7 @@ typedef off_t off64_t;
 
 #include <errno.h>
 #include <cmath>
+#include <fcntl.h>
 
 #include <pbd/error.h>
 #include <ardour/destructive_filesource.h>
@@ -108,22 +109,24 @@ DestructiveFileSource::setup_standard_crossfades (jack_nframes_t rate)
 
                /* XXXX THIS IS NOT THE RIGHT XFADE CURVE: USE A PROPER VOLUMETRIC EQUAL POWER CURVE */
 
-               out_coefficient[n] = n/(gain_t) xfade_frames;
-               in_coefficient[n] = 1.0 - out_coefficient[n];
+               in_coefficient[n] = n/(gain_t) (xfade_frames-1); /* 0 .. 1 */
+               out_coefficient[n] = 1.0 - in_coefficient[n];    /* 1 .. 0 */
        }
 }
 
 int
 DestructiveFileSource::seek (jack_nframes_t frame)
 {
-       file_pos = data_offset + (sizeof (Sample) * frame);
+//     file_pos = data_offset + (sizeof (Sample) * frame);
+       cerr << _name << " Seek to " << frame << " = " << data_offset + (sizeof (Sample) * frame) << endl;
        return 0;
 }
 
 void
-DestructiveFileSource::mark_capture_start ()
+DestructiveFileSource::mark_capture_start (jack_nframes_t pos)
 {
        _capture_start = true;
+       capture_start_frame = pos;
 }
 
 void
@@ -140,74 +143,106 @@ DestructiveFileSource::clear_capture_marks ()
 }      
 
 jack_nframes_t
-DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int dir)
+DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in)
 {
        jack_nframes_t xfade = min (xfade_frames, cnt);
        jack_nframes_t xfade_bytes = xfade * sizeof (Sample);
-       
-       if (::pread64 (fd, (char *) xfade_buf, xfade_bytes, file_pos) != (off64_t) xfade_bytes) {
-               error << string_compose(_("FileSource: \"%1\" bad read (%2)"), _path, strerror (errno)) << endmsg;
-               return 0;
+       jack_nframes_t nofade = cnt - xfade;
+       jack_nframes_t nofade_bytes = nofade * sizeof (Sample);
+       Sample* fade_data = 0;
+       off_t fade_position = 0;
+
+       if (fade_in) {
+               fade_position = file_pos;
+               fade_data = data;
+       } else {
+               fade_position = file_pos + nofade_bytes;
+               fade_data = data + nofade;
+       }
+
+       if (::pread64 (fd, (char *) xfade_buf, xfade_bytes, fade_position) != (off64_t) xfade_bytes) {
+               if (errno == EAGAIN) {
+                       /* no data there, so no xfade */
+
+                       xfade = 0;
+                       xfade_bytes = 0;
+                       nofade = cnt;
+                       nofade_bytes = nofade * sizeof (Sample);
+
+               } else {
+                       error << string_compose(_("FileSource: \"%1\" bad read (%2: %3)"), _path, errno, strerror (errno)) << endmsg;
+                       return 0;
+               }
+       }
+
+       if (nofade && !fade_in) {
+               cerr << "write " << nofade_bytes << " of prefade OUT data to " << file_pos << " .. " << file_pos + nofade_bytes << endl;
+               if (::pwrite64 (fd, (char *) data, nofade_bytes, file_pos) != (off64_t) nofade_bytes) {
+                       error << string_compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
+                       return 0;
+               }
        }
 
        if (xfade == xfade_frames) {
 
+               jack_nframes_t n;
+
                /* use the standard xfade curve */
                
-               if (dir) {
+               if (fade_in) {
 
                        /* fade new material in */
-
-                       for (jack_nframes_t n = 0; n < xfade; ++n) {
-                               xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (data[n] * in_coefficient[n]);
+                       
+                       for (n = 0; n < xfade; ++n) {
+                               xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (fade_data[n] * in_coefficient[n]);
                        }
+
                } else {
 
+
                        /* fade new material out */
                        
-                       
-                       for (jack_nframes_t n = 0; n < xfade; ++n) {
-                               xfade_buf[n] = (xfade_buf[n] * in_coefficient[n]) + (data[n] * out_coefficient[n]);
+                       for (n = 0; n < xfade; ++n) {
+                               xfade_buf[n] = (xfade_buf[n] * in_coefficient[n]) + (fade_data[n] * out_coefficient[n]);
                        }
                }
 
-
-       } else {
+       } else if (xfade) {
 
                /* short xfade, compute custom curve */
 
+               /* XXX COMPUTE THE CURVE, DAMMIT! */
+
                for (jack_nframes_t n = 0; n < xfade; ++n) {
-                       xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (data[n] * in_coefficient[n]);
+                       xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (fade_data[n] * in_coefficient[n]);
                }
        }
-       
-       if (::pwrite64 (fd, (char *) xfade_buf, xfade, file_pos) != (off64_t) xfade_bytes) {
-               error << string_compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
-               return 0;
-       }
 
-       /* don't advance file_pos here; if the write fails, we want it left where it was before the overall
-          write, not in the middle of it.
-       */
+       if (xfade) {
+               cerr << "write " << xfade_bytes << " of xfade  data to " << fade_position << " .. " << fade_position + xfade_bytes << endl;
+               if (::pwrite64 (fd, (char *) xfade_buf, xfade_bytes, fade_position) != (off64_t) xfade_bytes) {
+                       error << string_compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
+                       return 0;
+               }
+       }
        
-       if (xfade < cnt) {
-               jack_nframes_t remaining = (cnt - xfade);
-               int32_t bytes = remaining * sizeof (Sample);
-
-               if (::pwrite64 (fd, (char *) data + remaining, bytes, file_pos) != (off64_t) bytes) {
+       if (fade_in && nofade) {
+               cerr << "write " << nofade_bytes << " of postfade IN  data to " << file_pos + xfade_bytes << " .. " 
+                    << file_pos + xfade_bytes + nofade_bytes << endl;
+               if (::pwrite64 (fd, (char *) (data + xfade), nofade_bytes, file_pos + xfade_bytes) != (off64_t) nofade_bytes) {
                        error << string_compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
                        return 0;
                }
        }
 
-       file_pos += cnt;
-
        return cnt;
 }
 
 jack_nframes_t
 DestructiveFileSource::write (Sample* data, jack_nframes_t cnt)
 {
+       cerr << _name << ": write " << cnt << " to " << file_pos << " start ? " << _capture_start << " end ? " << _capture_end << endl;
+
        {
                LockMonitor lm (_lock, __LINE__, __FILE__);
                
@@ -216,11 +251,21 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt)
 
                if (_capture_start) {
                        _capture_start = false;
+                       _capture_end = false;
+
+                       /* move to the correct location place */
+                       file_pos = data_offset + (capture_start_frame * sizeof (Sample));
+
+                       cerr << "First byte of capture will be at " << file_pos << endl;
+                       
                        if (crossfade (data, cnt, 1) != cnt) {
                                return 0;
                        }
+
                } else if (_capture_end) {
+                       _capture_start = false;
                        _capture_end = false;
+
                        if (crossfade (data, cnt, 0) != cnt) {
                                return 0;
                        }
@@ -231,13 +276,15 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt)
                        }
                }
 
-               oldlen = file_pos;
+               oldlen = _length;
                if (file_pos + cnt > _length) {
                        _length += cnt;
                }
                _write_data_count = byte_cnt;
                file_pos += byte_cnt;
 
+               cerr << "at end of write, file_pos = " << file_pos << endl;
+
                if (_build_peakfiles) {
                        PeakBuildRecord *pbr = 0;
                        
@@ -269,3 +316,8 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt)
        return cnt;
 }
 
+jack_nframes_t
+DestructiveFileSource::last_capture_start_frame () const
+{
+       return capture_start_frame;
+}
index 09f9fcdd9da111eb4ebc5368f069ffcd2defa9fa..154e085858862b5c3eb99a226ee4992ee8c3afba 100644 (file)
@@ -614,6 +614,13 @@ DiskStream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t
                        
                }
 
+               if (_flags & Recordable) {
+                       cerr << "START RECORD @ " << capture_start_frame << " = " << capture_start_frame * sizeof (Sample) << endl;
+                       for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+                               (*chan).write_source->mark_capture_start (capture_start_frame);
+                       }
+               }
+
        } else if (!record_enabled() || !can_record) {
                
                /* stop recording */
@@ -1060,11 +1067,8 @@ DiskStream::seek (jack_nframes_t frame, bool complete_refill)
        for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
                (*chan).playback_buf->reset ();
                (*chan).capture_buf->reset ();
-               if (destructive()) {
-                       DestructiveFileSource* dfs = dynamic_cast<DestructiveFileSource*> ((*chan).write_source);
-                       if (dfs) {
-                               dfs->seek (frame);
-                       }
+               if ((*chan).write_source) {
+                       (*chan).write_source->seek (frame);
                }
        }
        
@@ -1616,7 +1620,7 @@ DiskStream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture
        */
 
        try {
-               region = new AudioRegion (srcs, 0, total_capture, 
+               region = new AudioRegion (srcs, channels[0].write_source->last_capture_start_frame(), total_capture, 
                                          region_name_from_path (channels[0].write_source->name()), 
                                          0, AudioRegion::Flag (AudioRegion::DefaultFlags|AudioRegion::Automatic|AudioRegion::WholeFile));
 
@@ -1635,7 +1639,7 @@ DiskStream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture
        _session.add_undo (_playlist->get_memento());
        _playlist->freeze ();
                
-       for (buffer_position = 0, ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
+       for (buffer_position = channels[0].write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
 
                string region_name;
                _session.region_name (region_name, _name, false);
@@ -1683,6 +1687,13 @@ DiskStream::finish_capture (bool rec_monitors_input)
 {
        was_recording = false;
        
+       if (_flags & Recordable) {
+               cerr << "STOP CAPTURE\n";
+               for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+                       (*chan).write_source->mark_capture_end ();
+               }
+       }
+       
        if (capture_captured == 0) {
                return;
        }
index 1a79b9f81e3a7f22c1a5d91513369dc822c04e58..b329c16cc6ee6454009a3bc77e76061b8477dc32 100644 (file)
@@ -1320,6 +1320,10 @@ Session::maybe_enable_record ()
 {
        atomic_set (&_record_status, Enabled);
 
+       /* XXX this save should really happen in another thread. its needed so that
+          pending capture state can be recovered if we crash.
+       */
+
        save_state ("", true);
 
        if (_transport_speed) {
index 747d4be0cdb2dab79df930347281c280843a8076..1a46e1b90089f15e314d7fd2dd657eff2885ad80 100644 (file)
@@ -595,7 +595,7 @@ UI::send_request (Request *req)
                        abort ();
                }
                
-               cerr << "thread " << pthread_self() << " sent request " << req << " type = " << req->type << endl;
+               // cerr << "thread " << pthread_self() << " sent request " << req << " type = " << req->type << endl;
                rbuf->increment_write_ptr (1);
                write (signal_pipe[1], &c, 1);
        }