From: David Robillard Date: Sun, 12 Oct 2008 17:40:37 +0000 (+0000) Subject: MIDI looping fixes from torbenh. X-Git-Tag: 3.0-alpha5~4019 X-Git-Url: https://main.carlh.net/gitweb/?p=ardour.git;a=commitdiff_plain;h=2c4a08bc5752d1453248af564ca3303c2c6e341c MIDI looping fixes from torbenh. git-svn-id: svn://localhost/ardour2/branches/3.0@3932 d708f5d6-7413-0410-9779-e7cbd77b26cf --- diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h index 77a12be2d0..f433cf94a7 100644 --- a/libs/ardour/ardour/configuration_vars.h +++ b/libs/ardour/ardour/configuration_vars.h @@ -52,6 +52,7 @@ CONFIG_VARIABLE (RemoteModel, remote_model, "remote-model", MixerOrdered) /* disk operations */ CONFIG_VARIABLE (uint32_t, minimum_disk_io_bytes, "minimum-disk-io-bytes", 1024 * 256) +CONFIG_VARIABLE (float, midi_readahead, "midi-readahead", 1.0) CONFIG_VARIABLE (float, audio_track_buffer_seconds, "track-buffer-seconds", 5.0) CONFIG_VARIABLE (float, midi_track_buffer_seconds, "midi-track-buffer-seconds", 1.0) CONFIG_VARIABLE (uint32_t, disk_choice_space_threshold, "disk-choice-space-threshold", 57600000) diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index a3d4d6d0a4..56e704f88e 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -132,6 +132,8 @@ class MidiDiskstream : public Diskstream void non_realtime_input_change (); void non_realtime_locate (nframes_t location); + static void set_readahed_frames( nframes_t frames_ahead ) { midi_readahead = frames_ahead; } + protected: int seek (nframes_t which_sample, bool complete_refill = false); @@ -140,6 +142,7 @@ class MidiDiskstream : public Diskstream int process (nframes_t transport_frame, nframes_t nframes, nframes_t offset, bool can_record, bool rec_monitors_input); bool commit (nframes_t nframes); + static nframes_t midi_readahead; private: @@ -181,6 +184,8 @@ class MidiDiskstream : public Diskstream nframes_t _last_flush_frame; NoteMode _note_mode; MidiStateTracker _midistate_tracker; + volatile gint _frames_written_to_ringbuffer; + volatile gint _frames_read_from_ringbuffer; }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h index 6e827d2852..72bf7a0fe5 100644 --- a/libs/ardour/ardour/midi_ring_buffer.h +++ b/libs/ardour/ardour/midi_ring_buffer.h @@ -131,7 +131,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t //std::cerr << "MRB read " << start << " .. " << end << " + " << offset << std::endl; - while (read_space() > sizeof(EventTime) + sizeof(EventType) + sizeof(uint32_t)) { + while (read_space() >= sizeof(EventTime) + sizeof(EventType) + sizeof(uint32_t)) { full_peek(sizeof(EventTime), (uint8_t*)&ev_time); @@ -153,8 +153,10 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t // the next events timestamp will be non-monotonic. if (ev_type == LoopEventType) { ev_time -= start; + ev_time += offset; Evoral::MIDIEvent loopevent(LoopEventType, ev_time); dst.push_back(loopevent); + // We can safely return, without reading the data, because // a LoopEvent does not have data. diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index 2372d91c5d..5b81401c41 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -57,6 +57,8 @@ using namespace std; using namespace ARDOUR; using namespace PBD; +nframes_t MidiDiskstream::midi_readahead = 4096; + MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::Flag flag) : Diskstream(sess, name, flag) , _playback_buf(0) @@ -64,6 +66,8 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F , _source_port(0) , _last_flush_frame(0) , _note_mode(Sustained) + , _frames_written_to_ringbuffer(0) + , _frames_read_from_ringbuffer(0) { /* prevent any write sources from being created */ @@ -84,6 +88,8 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node) , _source_port(0) , _last_flush_frame(0) , _note_mode(Sustained) + , _frames_written_to_ringbuffer(0) + , _frames_read_from_ringbuffer(0) { in_set_state = true; init (Recordable); @@ -623,9 +629,11 @@ MidiDiskstream::commit (nframes_t nframes) || _capture_buf->read_space() >= disk_io_chunk_frames; }*/ - /* we'll just keep the playback buffer full for now. - * this should be decreased to reduce edit latency */ - need_butler = _playback_buf->write_space() >= _playback_buf->capacity() / 2; + // Use The Counters To calculate how much time the Ringbuffer holds. + uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer); + uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer); + if ((frames_written - frames_read) <= midi_readahead) + need_butler = true; if (commit_should_unlock) { state_lock.unlock(); @@ -649,7 +657,7 @@ MidiDiskstream::set_pending_overwrite (bool yn) int MidiDiskstream::overwrite_existing_buffers () { - read(overwrite_frame, disk_io_chunk_frames, false); + //read(overwrite_frame, disk_io_chunk_frames, false); overwrite_queued = false; pending_overwrite = false; @@ -664,6 +672,8 @@ MidiDiskstream::seek (nframes_t frame, bool complete_refill) _playback_buf->reset(); _capture_buf->reset(); + g_atomic_int_set(&_frames_read_from_ringbuffer, 0); + g_atomic_int_set(&_frames_written_to_ringbuffer, 0); playback_sample = frame; file_frame = frame; @@ -680,7 +690,9 @@ MidiDiskstream::seek (nframes_t frame, bool complete_refill) int MidiDiskstream::can_internal_playback_seek (nframes_t distance) { - if (_playback_buf->read_space() < distance) { + uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer); + uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer); + if ((frames_written-frames_read) < distance) { return false; } else { return true; @@ -760,6 +772,8 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed) start) << endmsg; return -1; } + //cout << "this write " << this_read << "start= " << start << endl; + g_atomic_int_add(&_frames_written_to_ringbuffer, this_read); _read_data_count = _playlist->read_data_count(); @@ -777,6 +791,9 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed) // Synthesize LoopEvent here, because the next events // written will have non-monotonic timestamps. _playback_buf->write(loop_end - 1, LoopEventType, 0, 0); + //cout << "Pushing LoopEvent ts=" << loop_end-1 + // << " start+this_read " << start+this_read << endl; + start = loop_start; } else { start += this_read; @@ -820,7 +837,20 @@ MidiDiskstream::do_refill () assert(_playback_buf->write_space() > 0); // ... have something to write to, and assert(file_frame <= max_frames); // ... something to write - nframes_t to_read = min(disk_io_chunk_frames, (max_frames - file_frame)); + // now calculate how much time is in the ringbuffer. + // and lets write as much as we need to get this to be midi_readahead; + uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer); + uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer); + if ((frames_written-frames_read) >= midi_readahead) { + //cout << "Nothing to do. all fine" << endl; + return 0; + } + + nframes_t to_read = midi_readahead - (frames_written - frames_read); + + //cout << "read for midi_readahead " << to_read << " rb_contains: " << frames_written-frames_read << endl; + + to_read = min(to_read, (max_frames - file_frame)); if (read (file_frame, to_read, reversed)) { ret = -1; @@ -1466,6 +1496,10 @@ MidiDiskstream::get_playback(MidiBuffer& dst, nframes_t start, nframes_t end, nf // Translates stamps to be relative to start, but add offset. _playback_buf->read(dst, start, end, offset); + gint32 data_read = end-start; + //cout << "data read = " << data_read << " e=" << end << " s=" << start << "off= " << offset + // << " readspace " << _playback_buf->read_space() << " writespace " << _playback_buf->write_space() << endl; + g_atomic_int_add(&_frames_read_from_ringbuffer, data_read); // Now feed the data through the MidiStateTracker. // In case it detects a LoopEvent it will add necessary note diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index eac71fb5d1..02f8569a3d 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -76,6 +77,7 @@ Session::start_butler_thread () * (i.e. how many MIDI bytes we might see in a cycle) */ midi_dstream_buffer_size = (uint32_t) floor (Config->get_midi_track_buffer_seconds() * (float)frame_rate()); + MidiDiskstream::set_readahed_frames ((nframes_t) (Config->get_midi_readahead() * (float) frame_rate())); Crossfade::set_buffer_size (audio_dstream_buffer_size);