X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fdestructive_filesource.cc;h=2f2e85ed5a088652ad7cd59f3c09de66af79d502;hb=f3e5450492109bb4fab898ae824e30ede28bf7b5;hp=c18fedd982aee4d3b2a3536dad64762c01c1bd05;hpb=7df20e1166b3c8878de5525cf3e8395f942e7177;p=ardour.git diff --git a/libs/ardour/destructive_filesource.cc b/libs/ardour/destructive_filesource.cc index c18fedd982..2f2e85ed5a 100644 --- a/libs/ardour/destructive_filesource.cc +++ b/libs/ardour/destructive_filesource.cc @@ -55,43 +55,51 @@ typedef off_t off64_t; #include #include +#include #include +#include +#include #include "i18n.h" using namespace std; using namespace ARDOUR; +using namespace PBD; gain_t* DestructiveFileSource::out_coefficient = 0; gain_t* DestructiveFileSource::in_coefficient = 0; -jack_nframes_t DestructiveFileSource::xfade_frames = 64; +nframes_t DestructiveFileSource::xfade_frames = 64; -DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate, bool repair_first, SampleFormat samp_format) - : FileSource (path, rate, repair_first, samp_format) +DestructiveFileSource::DestructiveFileSource (Session& s, string path, SampleFormat samp_format, HeaderFormat hdr_format, nframes_t rate, Flag flags) + : SndFileSource (s, path, samp_format, hdr_format, rate, flags) { - if (out_coefficient == 0) { - setup_standard_crossfades (rate); - } + init (); +} - xfade_buf = new Sample[xfade_frames]; - _capture_start = false; - _capture_end = false; - file_pos = 0; +DestructiveFileSource::DestructiveFileSource (Session& s, string path, Flag flags) + : SndFileSource (s, path, flags) +{ + init (); } -DestructiveFileSource::DestructiveFileSource (const XMLNode& node, jack_nframes_t rate) - : FileSource (node, rate) +DestructiveFileSource::DestructiveFileSource (Session& s, const XMLNode& node) + : SndFileSource (s, node) { - if (out_coefficient == 0) { - setup_standard_crossfades (rate); - } + init (); +} +void +DestructiveFileSource::init () +{ xfade_buf = new Sample[xfade_frames]; _capture_start = false; _capture_end = false; file_pos = 0; + + timeline_position = header_position_offset; + AudioFileSource::HeaderPositionOffsetChanged.connect (mem_fun (*this, &DestructiveFileSource::handle_header_position_change)); } DestructiveFileSource::~DestructiveFileSource() @@ -100,33 +108,37 @@ DestructiveFileSource::~DestructiveFileSource() } void -DestructiveFileSource::setup_standard_crossfades (jack_nframes_t rate) +DestructiveFileSource::setup_standard_crossfades (nframes_t rate) { - xfade_frames = (jack_nframes_t) floor ((/*Config->get_destructive_crossfade_msecs()*/ 64 / 1000.0) * rate); + /* This static method is assumed to have been called by the Session + before any DFS's are created. + */ - out_coefficient = new gain_t[xfade_frames]; - in_coefficient = new gain_t[xfade_frames]; - - for (jack_nframes_t n = 0; n < xfade_frames; ++n) { + xfade_frames = (nframes_t) floor ((Config->get_destructive_xfade_msecs () / 1000.0) * rate); - /* XXXX THIS IS NOT THE RIGHT XFADE CURVE: USE A PROPER VOLUMETRIC EQUAL POWER CURVE */ + if (out_coefficient) { + delete [] out_coefficient; + } - in_coefficient[n] = n/(gain_t) (xfade_frames-1); /* 0 .. 1 */ - out_coefficient[n] = 1.0 - in_coefficient[n]; /* 1 .. 0 */ + if (in_coefficient) { + delete [] in_coefficient; } -} -int -DestructiveFileSource::seek (jack_nframes_t frame) -{ - return 0; + out_coefficient = new gain_t[xfade_frames]; + in_coefficient = new gain_t[xfade_frames]; + + compute_equal_power_fades (xfade_frames, in_coefficient, out_coefficient); } void -DestructiveFileSource::mark_capture_start (jack_nframes_t pos) +DestructiveFileSource::mark_capture_start (nframes_t pos) { - _capture_start = true; - capture_start_frame = pos; + if (pos < timeline_position) { + _capture_start = false; + } else { + _capture_start = true; + capture_start_frame = pos; + } } void @@ -142,15 +154,15 @@ DestructiveFileSource::clear_capture_marks () _capture_end = false; } -jack_nframes_t -DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in, char * workbuf) +nframes_t +DestructiveFileSource::crossfade (Sample* data, nframes_t cnt, int fade_in) { - jack_nframes_t xfade = min (xfade_frames, cnt); - jack_nframes_t nofade = cnt - xfade; + nframes_t xfade = min (xfade_frames, cnt); + nframes_t nofade = cnt - xfade; Sample* fade_data = 0; - jack_nframes_t fade_position = 0; // in frames + nframes_t fade_position = 0; // in frames ssize_t retval; - jack_nframes_t file_cnt; + nframes_t file_cnt; if (fade_in) { fade_position = file_pos; @@ -180,7 +192,8 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in, } if (file_cnt) { - if ((retval = file_read (xfade_buf, fade_position, file_cnt, workbuf)) != (ssize_t) file_cnt) { + + if ((retval = read_unlocked (xfade_buf, fade_position, file_cnt)) != (ssize_t) file_cnt) { if (retval >= 0 && errno == EAGAIN) { /* XXX - can we really trust that errno is meaningful here? yes POSIX, i'm talking to you. * short or no data there */ @@ -193,12 +206,12 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in, } if (file_cnt != xfade) { - jack_nframes_t delta = xfade - file_cnt; + nframes_t delta = xfade - file_cnt; memset (xfade_buf+file_cnt, 0, sizeof (Sample) * delta); } if (nofade && !fade_in) { - if (file_write (data, file_pos, nofade, workbuf) != (ssize_t) nofade) { + if (write_float (data, file_pos, nofade) != nofade) { error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg; return 0; } @@ -206,7 +219,7 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in, if (xfade == xfade_frames) { - jack_nframes_t n; + nframes_t n; /* use the standard xfade curve */ @@ -230,24 +243,27 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in, } else if (xfade) { + gain_t in[xfade]; + gain_t out[xfade]; + /* short xfade, compute custom curve */ - /* XXX COMPUTE THE CURVE, DAMMIT! */ + compute_equal_power_fades (xfade, in, out); - for (jack_nframes_t n = 0; n < xfade; ++n) { - xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (fade_data[n] * in_coefficient[n]); + for (nframes_t n = 0; n < xfade; ++n) { + xfade_buf[n] = (xfade_buf[n] * out[n]) + (fade_data[n] * in[n]); } } if (xfade) { - if (file_write (xfade_buf, fade_position, xfade, workbuf) != (ssize_t) xfade) { + if (write_float (xfade_buf, fade_position, xfade) != xfade) { error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg; return 0; } } if (fade_in && nofade) { - if (file_write (data + xfade, file_pos + xfade, nofade, workbuf) != (ssize_t) nofade) { + if (write_float (data + xfade, file_pos + xfade, nofade) != nofade) { error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg; return 0; } @@ -256,109 +272,118 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in, return cnt; } -jack_nframes_t -DestructiveFileSource::write (Sample* data, jack_nframes_t cnt, char * workbuf) +nframes_t +DestructiveFileSource::write_unlocked (Sample* data, nframes_t cnt) { - cerr << _name << ": write " << cnt << " to " << file_pos << " start ? " << _capture_start << " end ? " << _capture_end << endl; + nframes_t old_file_pos; + + if (!writable()) { + return 0; + } + + if (_capture_start && _capture_end) { - { - LockMonitor lm (_lock, __LINE__, __FILE__); + /* start and end of capture both occur within the data we are writing, + so do both crossfades. + */ + + _capture_start = false; + _capture_end = false; + + /* move to the correct location place */ + file_pos = capture_start_frame - timeline_position; + + // split cnt in half + nframes_t subcnt = cnt / 2; + nframes_t ofilepos = file_pos; + + // fade in + if (crossfade (data, subcnt, 1) != subcnt) { + return 0; + } - jack_nframes_t old_file_pos; + file_pos += subcnt; + Sample * tmpdata = data + subcnt; + + // fade out + subcnt = cnt - subcnt; + if (crossfade (tmpdata, subcnt, 0) != subcnt) { + return 0; + } + + file_pos = ofilepos; // adjusted below - if (_capture_start && _capture_end) { - _capture_start = false; - _capture_end = false; + } else if (_capture_start) { - /* move to the correct location place */ - file_pos = capture_start_frame; - - cerr << "First frame of capture will be at " << file_pos << " and last at: " << file_pos + cnt << endl; + /* start of capture both occur within the data we are writing, + so do the fade in + */ - // split cnt in half - jack_nframes_t subcnt = cnt / 2; - jack_nframes_t ofilepos = file_pos; - - // fade in - if (crossfade (data, subcnt, 1, workbuf) != subcnt) { - return 0; - } + _capture_start = false; + _capture_end = false; + + /* move to the correct location place */ + file_pos = capture_start_frame - timeline_position; - file_pos += subcnt; - Sample * tmpdata = data + subcnt; - - // fade out - subcnt = cnt - subcnt; - if (crossfade (tmpdata, subcnt, 0, workbuf) != subcnt) { - return 0; - } + if (crossfade (data, cnt, 1) != cnt) { + return 0; + } + + } else if (_capture_end) { + + /* end of capture both occur within the data we are writing, + so do the fade out + */ - file_pos = ofilepos; // adjusted below + _capture_start = false; + _capture_end = false; + + if (crossfade (data, cnt, 0) != cnt) { + return 0; } - else if (_capture_start) { - _capture_start = false; - _capture_end = false; - /* move to the correct location place */ - file_pos = capture_start_frame; - - cerr << "First frame of capture will be at " << file_pos << endl; - - if (crossfade (data, cnt, 1, workbuf) != cnt) { - return 0; - } + } else { - } else if (_capture_end) { - _capture_start = false; - _capture_end = false; + /* in the middle of recording */ - if (crossfade (data, cnt, 0, workbuf) != cnt) { - return 0; - } - } else { - if (file_write(data, file_pos, cnt, workbuf) != (ssize_t) cnt) { - return 0; - } + if (write_float (data, file_pos, cnt) != cnt) { + return 0; } + } + + old_file_pos = file_pos; + update_length (file_pos, cnt); + file_pos += cnt; - old_file_pos = file_pos; - if (file_pos + cnt > _length) { - _length = file_pos + cnt; + if (_build_peakfiles) { + PeakBuildRecord *pbr = 0; + + if (pending_peak_builds.size()) { + pbr = pending_peak_builds.back(); } - file_pos += cnt; - //cerr << this << ' ' << _name << " at end of write, file_pos = " << file_pos << " length = " << ((int) &_length - (int) this) << ' ' << &_length << ' ' << _length << endl; - - if (_build_peakfiles) { - PeakBuildRecord *pbr = 0; + if (pbr && pbr->frame + pbr->cnt == old_file_pos) { - if (pending_peak_builds.size()) { - pbr = pending_peak_builds.back(); - } - - if (pbr && pbr->frame + pbr->cnt == old_file_pos) { - - /* the last PBR extended to the start of the current write, - so just extend it again. - */ - - pbr->cnt += cnt; - } else { - pending_peak_builds.push_back (new PeakBuildRecord (old_file_pos, cnt)); - } + /* the last PBR extended to the start of the current write, + so just extend it again. + */ - _peaks_built = false; + pbr->cnt += cnt; + } else { + pending_peak_builds.push_back (new PeakBuildRecord (old_file_pos, cnt)); } + + _peaks_built = false; } if (_build_peakfiles) { - queue_for_peaks (*this); + queue_for_peaks (shared_from_this ()); } - + return cnt; } -jack_nframes_t +nframes_t DestructiveFileSource::last_capture_start_frame () const { return capture_start_frame; @@ -367,7 +392,33 @@ DestructiveFileSource::last_capture_start_frame () const XMLNode& DestructiveFileSource::get_state () { - XMLNode& node = FileSource::get_state (); + XMLNode& node = AudioFileSource::get_state (); node.add_property (X_("destructive"), "true"); return node; } + +void +DestructiveFileSource::handle_header_position_change () +{ + if ( _length != 0 ) { + error << string_compose(_("Filesource: start time is already set for existing file (%1): Cannot change start time."), _path ) << endmsg; + //in the future, pop up a dialog here that allows user to regenerate file with new start offset + } else if (writable()) { + timeline_position = header_position_offset; + set_header_timeline_position (); //this will get flushed if/when the file is recorded to + } +} + +void +DestructiveFileSource::set_timeline_position (nframes_t pos) +{ + //destructive track timeline postion does not change except at instantion or when header_position_offset (session start) changes +} + +int +DestructiveFileSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_unit) const +{ + // cerr << _name << " read peaks at " << start << " for " << cnt << " tpos = " << timeline_position << endl; + return AudioFileSource::read_peaks (peaks, npeaks, start, cnt, samples_per_unit); +} +