diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index d36d533e31..fcb5d39bc5 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -50,6 +50,7 @@ #include "ardour/region_factory.h" #include "ardour/session.h" #include "ardour/session_playlists.h" +#include "ardour/sndfile_helpers.h" #include "ardour/source_factory.h" #include "ardour/track.h" #include "ardour/types.h" @@ -1079,8 +1080,7 @@ AudioDiskstream::_do_refill_with_alloc (bool partial_fill) Sample* mix_buf = new Sample[1048576]; float* gain_buf = new float[1048576]; - int ret = _do_refill (mix_buf, gain_buf, (partial_fill ? - (_session.butler()->audio_diskstream_playback_buffer_size() / 4.0) : 0)); + int ret = _do_refill (mix_buf, gain_buf, (partial_fill ? disk_read_chunk_frames : 0)); delete [] mix_buf; delete [] gain_buf; @@ -1111,6 +1111,14 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecn boost::shared_ptr c = channels.reader(); framecnt_t ts; + /* do not read from disk while session is marked as Loading, to avoid + useless redundant I/O. + */ + + if (_session.state_of_the_state() & Session::Loading) { + return 0; + } + if (c->empty()) { return 0; } @@ -1130,12 +1138,17 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecn return 0; } - if (fill_level && (fill_level < total_space)) { - cerr << name() << " adjust total space of " << total_space << " to leave " << fill_level << " to still refill\n"; - if (fill_level < 0) { - PBD::stacktrace (cerr, 20); + if (fill_level) { + if (fill_level < total_space) { + cerr << name() << " adjust total space of " << total_space << " to leave " << fill_level << " to still refill\n"; + if (fill_level < 0) { + PBD::stacktrace (cerr, 20); + } + total_space -= fill_level; + } else { + /* we can't do anything with it */ + fill_level = 0; } - total_space -= fill_level; } /* if we're running close to normal speed and there isn't enough @@ -1228,33 +1241,29 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecn framepos_t file_frame_tmp = 0; - /* this needs to be 32 bit for the power-of-two hack below to work. - Clever, but poses ugly casting problems since the value is - semantically a framecnt_t. + /* total_space is in samples. We want to optimize read sizes in various sizes using bytes */ + + const size_t bits_per_sample = sndfile_data_width (_session.config.get_native_file_data_format()); + size_t total_bytes = total_space * bits_per_sample / 8; + + /* chunk size range is 256kB to 4MB. Bigger is faster in terms of MB/sec, but bigger chunk size always takes longer */ + size_t byte_size_for_read = max ((size_t) (256 * 1024), min ((size_t) (4 * 1048576), total_bytes)); - uint32_t chunk_size_for_read = (uint32_t) max ((framecnt_t) 65536, min ((framecnt_t) 1048576, total_space)); + /* find nearest (lower) multiple of 16384 */ - /* if not already a power of 2, go to next lower power of 2 */ + byte_size_for_read = (byte_size_for_read / 16384) * 16384; - if ((chunk_size_for_read & (chunk_size_for_read - 1)) != 0) { + /* now back to samples */ - /* move to the next largest power of two. Hack from stanford bithacks page. */ - - chunk_size_for_read--; - chunk_size_for_read |= chunk_size_for_read >> 1; - chunk_size_for_read |= chunk_size_for_read >> 2; - chunk_size_for_read |= chunk_size_for_read >> 4; - chunk_size_for_read |= chunk_size_for_read >> 8; - chunk_size_for_read |= chunk_size_for_read >> 16; - chunk_size_for_read++; - - /* go back to previous power */ - - chunk_size_for_read >>= 1; - } + framecnt_t samples_to_read = byte_size_for_read / (bits_per_sample / 8); + + //cerr << name() << " will read " << byte_size_for_read << " out of total bytes " << total_bytes << " in buffer of " + // << c->front()->playback_buf->bufsize() * bits_per_sample / 8 << " bps = " << bits_per_sample << endl; + cerr << name () << " read samples = " << samples_to_read << " out of total space " << total_space << " in buffer of " << c->front()->playback_buf->bufsize() << " samples\n"; - cerr << name() << " will read " << chunk_size_for_read << " out of total space " << total_space << " in buffer of " << c->front()->playback_buf->bufsize() << endl; + uint64_t before = g_get_monotonic_time (); + uint64_t elapsed; for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) { @@ -1265,7 +1274,7 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecn chan->playback_buf->get_write_vector (&vector); - if ((framecnt_t) vector.len[0] > chunk_size_for_read) { + if ((framecnt_t) vector.len[0] > samples_to_read) { /* we're not going to fill the first chunk, so certainly do not bother with the other part. it won't be connected with the part we do fill, as in: @@ -1297,7 +1306,7 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecn len2 = vector.len[1]; to_read = min (ts, len1); - to_read = min (to_read, (framecnt_t) chunk_size_for_read); + to_read = min (to_read, (framecnt_t) samples_to_read); assert (to_read >= 0); @@ -1317,7 +1326,7 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecn if (to_read) { /* we read all of vector.len[0], but it wasn't the - entire chunk_size_for_read of data, so read some or + entire samples_to_read of data, so read some or all of vector.len[1] as well. */ @@ -1335,10 +1344,15 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecn } + elapsed = g_get_monotonic_time () - before; + cerr << "\tbandwidth = " << (byte_size_for_read / 1048576.0) / (elapsed/1000000.0) << "MB/sec\n"; + file_frame = file_frame_tmp; assert (file_frame >= 0); - ret = ((total_space - chunk_size_for_read) > disk_read_chunk_frames); + ret = ((total_space - samples_to_read) > disk_read_chunk_frames); + + c->front()->playback_buf->get_write_vector (&vector); out: return ret; diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index c0f717ec1c..b02bcb8dec 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -430,6 +430,7 @@ Session::Session (AudioEngine &eng, _is_new = false; session_loaded (); + BootMessage (_("Session loading complete")); } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 891c37e04c..7f2e22af1a 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -343,16 +343,36 @@ Session::post_engine_init () Port::set_connecting_blocked (false); DirtyChanged (); /* EMIT SIGNAL */ +} - if (_is_new) { - save_state (""); - } else if (state_was_pending) { - save_state (""); - remove_pending_capture_state (); - state_was_pending = false; - } +void +Session::session_loaded () +{ + SessionLoaded(); + + _state_of_the_state = Clean; + + DirtyChanged (); /* EMIT SIGNAL */ + + if (_is_new) { + save_state (""); + } else if (state_was_pending) { + save_state (""); + remove_pending_capture_state (); + state_was_pending = false; + } - return 0; + /* Now, finally, we can fill the playback buffers */ + + BootMessage (_("Filling playback buffers")); + + boost::shared_ptr rl = routes.reader(); + for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) { + boost::shared_ptr trk = boost::dynamic_pointer_cast (*r); + if (trk && !trk->hidden()) { + trk->seek (_transport_frame, true); + } + } } void diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 711c3e51e7..2656fd0d83 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -314,12 +314,13 @@ Session::butler_transport_work () bool finished; PostTransportWork ptw; boost::shared_ptr r = routes.reader (); - + uint64_t before; + int on_entry = g_atomic_int_get (&_butler->should_do_transport_work); finished = true; ptw = post_transport_work(); - DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), g_get_monotonic_time())); + DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time()))); if (ptw & PostTransportAdjustPlaybackBuffering) { for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { @@ -410,7 +411,7 @@ Session::butler_transport_work () g_atomic_int_dec_and_test (&_butler->should_do_transport_work); - DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done at %1\n"), g_get_monotonic_time())); + DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs\n"), g_get_monotonic_time() - before)); DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame))); }