X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudio_diskstream.cc;h=b3204c38b66d67a81c74964192b020ffa547f5fe;hb=c158c44fab4d5cd0a6fade9213b262849d90dc31;hp=e5dfb238db9058a8fe1c272cdd182c15238c7dec;hpb=eb6ae56fafa8cc1cf5309a33e40227a402ee608d;p=ardour.git diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index e5dfb238db..b3204c38b6 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -59,6 +59,7 @@ #include "ardour/source_factory.h" #include "ardour/utils.h" #include "ardour/session_playlists.h" +#include "ardour/route.h" #include "i18n.h" #include @@ -79,10 +80,7 @@ AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream: /* prevent any write sources from being created */ in_set_state = true; - - init(flag); use_new_playlist (); - in_set_state = false; } @@ -92,7 +90,7 @@ AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node) , channels (new ChannelList) { in_set_state = true; - init (Recordable); + init (); if (set_state (node, Stateful::loading_state_version)) { in_set_state = false; @@ -107,10 +105,8 @@ AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node) } void -AudioDiskstream::init (Diskstream::Flag f) +AudioDiskstream::init () { - Diskstream::init(f); - /* there are no channels at this point, so these two calls just get speed_buffer_size and wrap_buffer size setup without duplicating their code. @@ -326,7 +322,7 @@ AudioDiskstream::use_copy_playlist () newname = Playlist::bump_name (_playlist->name(), _session); - if ((playlist = boost::dynamic_pointer_cast(PlaylistFactory::create (audio_playlist(), newname))) != 0) { + if ((playlist = boost::dynamic_pointer_cast(PlaylistFactory::create (audio_playlist(), newname))) != 0) { playlist->set_orig_diskstream_id (id()); return use_playlist (playlist); } else { @@ -425,7 +421,7 @@ AudioDiskstream::prepare_record_status(nframes_t capture_start_frame) } int -AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input) +AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler) { uint32_t n; boost::shared_ptr c = channels.reader(); @@ -433,48 +429,26 @@ 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; - /* if we've already processed the frames corresponding to this call, - just return. this allows multiple routes that are taking input - from this diskstream to call our ::process() method, but have - this stuff only happen once. more commonly, it allows both - the AudioTrack that is using this AudioDiskstream *and* the Session - to call process() without problems. - */ - - if (_processed) { - return 0; - } - - commit_should_unlock = false; + playback_distance = 0; if (!_io || !_io->active()) { - _processed = true; return 0; } check_record_status (transport_frame, nframes, can_record); - nominally_recording = (can_record && re); - if (nframes == 0) { - _processed = true; return 0; } - /* This lock is held until the end of AudioDiskstream::commit, so these two functions - must always be called as a pair. The only exception is if this function - returns a non-zero value, in which case, ::commit should not be called. - */ + Glib::Mutex::Lock sm (state_lock, Glib::TRY_LOCK); - // If we can't take the state lock return. - if (!state_lock.trylock()) { + if (!sm.locked()) { return 1; } - commit_should_unlock = true; + adjust_capture_position = 0; for (chan = c->begin(); chan != c->end(); ++chan) { @@ -482,28 +456,35 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can (*chan)->current_playback_buffer = 0; } - if (nominally_recording || (_session.get_record_enabled() && _session.config.get_punch_in())) { - // 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); + /* two conditions to test for here: + + A: this track is rec-enabled, and the session has confirmed that we can record + B: this track is rec-enabled, has been recording, and we are set up for auto-punch-in - calculate_record_range(ot, transport_frame, nframes, rec_nframes, rec_offset); + The second test is necessary to capture the extra material that arrives AFTER the transport + frame has left the punch range (which will cause the "can_record" argument to be false). + */ - 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(); @@ -531,7 +512,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can AudioPort* const ap = _io->audio (n); assert(ap); assert(rec_nframes <= ap->get_audio_buffer(nframes).capacity()); - memcpy (chaninfo->current_capture_buffer, ap->get_audio_buffer (rec_nframes).data(rec_offset), sizeof (Sample) * rec_nframes); + memcpy (chaninfo->current_capture_buffer, ap->get_audio_buffer (nframes).data(rec_offset), sizeof (Sample) * rec_nframes); } else { @@ -591,7 +572,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*/ @@ -666,23 +647,15 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can _speed = _target_speed; - } + } ret = 0; - out: - _processed = true; - - if (ret) { - - /* we're exiting with failure, so ::commit will not - be called. unlock the state lock. - */ - - commit_should_unlock = false; - state_lock.unlock(); - } + if (commit (nframes)) { + need_butler = true; + } + out: return ret; } @@ -705,7 +678,7 @@ AudioDiskstream::process_varispeed_playback(nframes_t nframes, boost::shared_ptr } bool -AudioDiskstream::commit (nframes_t /*nframes*/) +AudioDiskstream::commit (nframes_t /* nframes */) { bool need_butler = false; @@ -749,12 +722,6 @@ AudioDiskstream::commit (nframes_t /*nframes*/) } } - if (commit_should_unlock) { - state_lock.unlock(); - } - - _processed = false; - return need_butler; } @@ -763,7 +730,7 @@ AudioDiskstream::set_pending_overwrite (bool yn) { /* called from audio thread, so we can use the read ptr and playback sample as we wish */ - pending_overwrite = yn; + _pending_overwrite = yn; overwrite_frame = playback_sample; overwrite_offset = channels.reader()->front()->playback_buf->get_read_ptr(); @@ -832,7 +799,7 @@ AudioDiskstream::overwrite_existing_buffers () ret = 0; out: - pending_overwrite = false; + _pending_overwrite = false; delete [] gain_buffer; delete [] mixdown_buffer; return ret; @@ -1368,7 +1335,7 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush) } void -AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture) +AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abort_capture) { uint32_t buffer_position; bool more_work = true; @@ -1506,7 +1473,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca string region_name; - _session.region_name (region_name, whole_file_region_name, false); + 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; @@ -1612,6 +1579,8 @@ void AudioDiskstream::finish_capture (bool /*rec_monitors_input*/, boost::shared_ptr c) { was_recording = false; + first_recordable_frame = max_frames; + last_recordable_frame = max_frames; if (capture_captured == 0) { return; @@ -1733,7 +1702,7 @@ AudioDiskstream::disengage_record_enable () XMLNode& AudioDiskstream::get_state () { - XMLNode* node = new XMLNode ("AudioDiskstream"); + XMLNode* node = new XMLNode ("Diskstream"); char buf[64] = ""; LocaleGuard lg (X_("POSIX")); boost::shared_ptr c = channels.reader(); @@ -1859,7 +1828,7 @@ AudioDiskstream::set_state (const XMLNode& node, int /*version*/) } if (!had_playlist) { - _playlist->set_orig_diskstream_id (_id); + _playlist->set_orig_diskstream_id (id()); } if (!destructive() && capture_pending_node) { @@ -1916,7 +1885,7 @@ AudioDiskstream::use_new_write_source (uint32_t n) } try { - if ((chan->write_source = _session.create_audio_source_for_session (*this, n, destructive())) == 0) { + if ((chan->write_source = _session.create_audio_source_for_session (n_channels().n_audio(), name(), n, destructive())) == 0) { throw failed_constructor(); } } @@ -2023,7 +1992,7 @@ AudioDiskstream::allocate_temporary_buffers () when slaving to MTC, Timecode etc. */ - double sp = max (fabsf (_actual_speed), 1.2f); + double const sp = max (fabsf (_actual_speed), 1.2f); nframes_t required_wrap_size = (nframes_t) floor (_session.get_block_size() * sp) + 1; if (required_wrap_size > wrap_buffer_size) { @@ -2087,8 +2056,10 @@ int AudioDiskstream::add_channel_to (boost::shared_ptr c, uint32_t how_many) { while (how_many--) { - c->push_back (new ChannelInfo(_session.butler()->audio_diskstream_buffer_size(), speed_buffer_size, wrap_buffer_size)); - interpolation.add_channel_to (_session.butler()->audio_diskstream_buffer_size(), speed_buffer_size); + c->push_back (new ChannelInfo(_session.butler()->audio_diskstream_playback_buffer_size(), + _session.butler()->audio_diskstream_capture_buffer_size(), + speed_buffer_size, wrap_buffer_size)); + interpolation.add_channel_to (_session.butler()->audio_diskstream_playback_buffer_size(), speed_buffer_size); } _n_channels.set(DataType::AUDIO, c->size()); @@ -2109,9 +2080,7 @@ int AudioDiskstream::remove_channel_from (boost::shared_ptr c, uint32_t how_many) { while (how_many-- && !c->empty()) { - // FIXME: crash (thread safe with RCU?) - // memory leak, when disabled.... :( - //delete c->back(); + delete c->back(); c->pop_back(); interpolation.remove_channel_from (); } @@ -2328,7 +2297,27 @@ AudioDiskstream::can_become_destructive (bool& requires_bounce) const return true; } -AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t bufsize, nframes_t speed_size, nframes_t wrap_size) +void +AudioDiskstream::adjust_playback_buffering () +{ + boost::shared_ptr c = channels.reader(); + + for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { + (*chan)->resize_playback (_session.butler()->audio_diskstream_playback_buffer_size()); + } +} + +void +AudioDiskstream::adjust_capture_buffering () +{ + boost::shared_ptr c = channels.reader(); + + for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { + (*chan)->resize_capture (_session.butler()->audio_diskstream_capture_buffer_size()); + } +} + +AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t playback_bufsize, nframes_t capture_bufsize, nframes_t speed_size, nframes_t wrap_size) { peak_power = 0.0f; source = 0; @@ -2340,8 +2329,8 @@ AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t bufsize, nframes_t speed_si playback_wrap_buffer = new Sample[wrap_size]; capture_wrap_buffer = new Sample[wrap_size]; - playback_buf = new RingBufferNPT (bufsize); - capture_buf = new RingBufferNPT (bufsize); + playback_buf = new RingBufferNPT (playback_bufsize); + capture_buf = new RingBufferNPT (capture_bufsize); capture_transition_buf = new RingBufferNPT (256); /* touch the ringbuffer buffers, which will cause @@ -2355,11 +2344,25 @@ AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t bufsize, nframes_t speed_si memset (capture_transition_buf->buffer(), 0, sizeof (CaptureTransition) * capture_transition_buf->bufsize()); } +void +AudioDiskstream::ChannelInfo::resize_playback (nframes_t playback_bufsize) +{ + delete playback_buf; + playback_buf = new RingBufferNPT (playback_bufsize); + memset (playback_buf->buffer(), 0, sizeof (Sample) * playback_buf->bufsize()); +} + +void +AudioDiskstream::ChannelInfo::resize_capture (nframes_t capture_bufsize) +{ + delete capture_buf; + capture_buf = new RingBufferNPT (capture_bufsize); + memset (capture_buf->buffer(), 0, sizeof (Sample) * capture_buf->bufsize()); +} + AudioDiskstream::ChannelInfo::~ChannelInfo () { - if (write_source) { - write_source.reset (); - } + write_source.reset (); delete [] speed_buffer; speed_buffer = 0; @@ -2379,3 +2382,4 @@ AudioDiskstream::ChannelInfo::~ChannelInfo () delete capture_transition_buf; capture_transition_buf = 0; } +