From 5a48f99f72c2e2f3ed313e00446dfdaa05dc5d56 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 15 Feb 2009 01:24:26 +0000 Subject: [PATCH] Use nframes_t for timestamps of real (jack) time MIDI events (i.e. in MidiBuffer and MidiRingBuffer). Use iterator interface of Sequence to read events in a MIDISource rather than Sequence::read, avoiding timestamp confusion. Disable no longer useful Sequence::read. git-svn-id: svn://localhost/ardour2/branches/3.0@4570 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/midi_buffer.h | 4 ++-- libs/ardour/ardour/midi_diskstream.h | 22 ++++++++++---------- libs/ardour/ardour/midi_playlist.h | 2 +- libs/ardour/ardour/midi_region.h | 8 +++----- libs/ardour/ardour/midi_source.h | 13 ++++++------ libs/ardour/ardour/midi_track.h | 5 ++--- libs/ardour/ardour/smf_source.h | 4 ++-- libs/ardour/meter.cc | 2 +- libs/ardour/midi_diskstream.cc | 4 ++-- libs/ardour/midi_playlist.cc | 3 +-- libs/ardour/midi_port.cc | 2 +- libs/ardour/midi_region.cc | 6 +++--- libs/ardour/midi_ring_buffer.cc | 2 +- libs/ardour/midi_source.cc | 30 +++++++++++++++++++++++----- libs/ardour/smf_source.cc | 12 ++++++----- libs/evoral/evoral/Sequence.hpp | 8 ++++++-- libs/evoral/src/Event.cpp | 1 + libs/evoral/src/Sequence.cpp | 24 ++++++++++++++++++---- libs/evoral/test/SequenceTest.cpp | 7 +++++-- 19 files changed, 100 insertions(+), 59 deletions(-) diff --git a/libs/ardour/ardour/midi_buffer.h b/libs/ardour/ardour/midi_buffer.h index f90cbfd8e3..8ea5e32e81 100644 --- a/libs/ardour/ardour/midi_buffer.h +++ b/libs/ardour/ardour/midi_buffer.h @@ -32,7 +32,7 @@ namespace ARDOUR { class MidiBuffer : public Buffer { public: - typedef double TimeType; + typedef nframes_t TimeType; MidiBuffer(size_t capacity); ~MidiBuffer(); @@ -45,7 +45,7 @@ public: bool push_back(const Evoral::MIDIEvent& event); bool push_back(const jack_midi_event_t& event); - uint8_t* reserve(double time, size_t size); + uint8_t* reserve(TimeType time, size_t size); void resize(size_t); diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index 7a0daf37e8..eddeaa451a 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -170,18 +170,16 @@ class MidiDiskstream : public Diskstream void engage_record_enable (); void disengage_record_enable (); - void check_note_onoffs(Evoral::MIDIEvent &event); - void emit_pending_note_offs(MidiBuffer &dst, nframes_t time); - - MidiRingBuffer* _playback_buf; - MidiRingBuffer* _capture_buf; - MidiPort* _source_port; - boost::shared_ptr _write_source; - nframes_t _last_flush_frame; - NoteMode _note_mode; - MidiStateTracker _midi_state_tracker; - volatile gint _frames_written_to_ringbuffer; - volatile gint _frames_read_from_ringbuffer; + + MidiRingBuffer* _playback_buf; + MidiRingBuffer* _capture_buf; + MidiPort* _source_port; + boost::shared_ptr _write_source; + nframes_t _last_flush_frame; + NoteMode _note_mode; + MidiStateTracker _midi_state_tracker; + volatile gint _frames_written_to_ringbuffer; + volatile gint _frames_read_from_ringbuffer; }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h index d7fdadb2f5..a956878348 100644 --- a/libs/ardour/ardour/midi_playlist.h +++ b/libs/ardour/ardour/midi_playlist.h @@ -47,7 +47,7 @@ public: ~MidiPlaylist (); - nframes_t read (MidiRingBuffer& buf, + nframes_t read (MidiRingBuffer& buf, nframes_t start, nframes_t cnt, uint32_t chan_n=0); int set_state (const XMLNode&); diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h index 781f815ec5..356e418fc1 100644 --- a/libs/ardour/ardour/midi_region.h +++ b/libs/ardour/ardour/midi_region.h @@ -48,8 +48,6 @@ template class MidiRingBuffer; class MidiRegion : public Region { public: - typedef double TimeType; - ~MidiRegion(); boost::shared_ptr midi_source (uint32_t n=0) const; @@ -58,13 +56,13 @@ class MidiRegion : public Region virtual nframes64_t read (Sample*, nframes64_t pos, nframes64_t cnt, int channel) const { return 0; } virtual nframes64_t readable_length() const { return length(); } - nframes_t read_at (MidiRingBuffer& dst, + nframes_t read_at (MidiRingBuffer& dst, nframes_t position, nframes_t dur, uint32_t chan_n = 0, NoteMode mode = Sustained) const; - nframes_t master_read_at (MidiRingBuffer& dst, + nframes_t master_read_at (MidiRingBuffer& dst, nframes_t position, nframes_t dur, uint32_t chan_n = 0, @@ -108,7 +106,7 @@ class MidiRegion : public Region MidiRegion (const SourceList &, const XMLNode&); private: - nframes_t _read_at (const SourceList&, MidiRingBuffer& dst, + nframes_t _read_at (const SourceList&, MidiRingBuffer& dst, nframes_t position, nframes_t dur, uint32_t chan_n = 0, diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index c0b105decd..2126b4b162 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -57,8 +57,8 @@ class MidiSource : public Source virtual uint32_t n_channels () const { return 1; } // FIXME: integrate this with the Readable::read interface somehow - virtual nframes_t midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const; - virtual nframes_t midi_write (MidiRingBuffer& src, nframes_t cnt); + virtual nframes_t midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const; + virtual nframes_t midi_write (MidiRingBuffer& src, nframes_t cnt); virtual void append_event_unlocked(EventTimeUnit unit, const Evoral::Event& ev) = 0; @@ -98,11 +98,9 @@ class MidiSource : public Source protected: virtual void flush_midi() = 0; - //virtual int flush_header() = 0; - //virtual int flush_footer() = 0; - virtual nframes_t read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const = 0; - virtual nframes_t write_unlocked (MidiRingBuffer& dst, nframes_t cnt) = 0; + virtual nframes_t read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const = 0; + virtual nframes_t write_unlocked (MidiRingBuffer& dst, nframes_t cnt) = 0; mutable Glib::Mutex _lock; string _captured_for; @@ -112,6 +110,9 @@ class MidiSource : public Source boost::shared_ptr _model; bool _writing; + + mutable Evoral::Sequence::const_iterator _model_iter; + mutable nframes_t _last_read_end; private: bool file_changed (string path); diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 09c64c2978..d4054066f1 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -90,7 +90,6 @@ public: void set_note_mode (NoteMode m); protected: - XMLNode& state (bool full); int _set_state (const XMLNode&, bool call_base); @@ -104,8 +103,8 @@ private: void set_state_part_two (); void set_state_part_three (); - MidiRingBuffer _immediate_events; - NoteMode _note_mode; + MidiRingBuffer _immediate_events; + NoteMode _note_mode; }; } /* namespace ARDOUR*/ diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h index 9981408abc..ccc03acd66 100644 --- a/libs/ardour/ardour/smf_source.h +++ b/libs/ardour/ardour/smf_source.h @@ -102,14 +102,14 @@ class SMFSource : public MidiSource, public Evoral::SMF { int init (string idstr, bool must_exist); nframes_t read_unlocked ( - MidiRingBuffer& dst, + MidiRingBuffer& dst, nframes_t start, nframes_t cn, nframes_t stamp_offset, nframes_t negative_stamp_offset) const; nframes_t write_unlocked ( - MidiRingBuffer& src, + MidiRingBuffer& src, nframes_t cnt); bool find (std::string path, bool must_exist, bool& is_new); diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc index 39d7f63221..31a88b16f0 100644 --- a/libs/ardour/meter.cc +++ b/libs/ardour/meter.cc @@ -50,7 +50,7 @@ PeakMeter::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_f // GUI needs a better MIDI meter, not much information can be // expressed through peaks alone for (MidiBuffer::iterator i = bufs.get_midi(n).begin(); i != bufs.get_midi(n).end(); ++i) { - const Evoral::MIDIEvent ev(*i, false); + const Evoral::MIDIEvent ev(*i, false); if (ev.is_note_on()) { const float this_vel = log(ev.buffer()[2] / 127.0 * (M_E*M_E-M_E) + M_E) - 1.0; //printf("V %d -> %f\n", (int)((Byte)ev.buffer[2]), this_vel); diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index af7a5d8873..41f8eb9e19 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -122,8 +122,8 @@ MidiDiskstream::init (Diskstream::Flag f) allocate_temporary_buffers (); const size_t size = _session.midi_diskstream_buffer_size(); - _playback_buf = new MidiRingBuffer (size); - _capture_buf = new MidiRingBuffer (size); + _playback_buf = new MidiRingBuffer(size); + _capture_buf = new MidiRingBuffer(size); _n_channels = ChanCount(DataType::MIDI, 1); diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc index 7139447a19..6105e6cfa2 100644 --- a/libs/ardour/midi_playlist.cc +++ b/libs/ardour/midi_playlist.cc @@ -124,8 +124,7 @@ struct RegionSortByLayer { /** Returns the number of frames in time duration read (eg could be large when 0 events are read) */ nframes_t -MidiPlaylist::read (MidiRingBuffer& dst, nframes_t start, - nframes_t dur, unsigned chan_n) +MidiPlaylist::read (MidiRingBuffer& dst, nframes_t start, nframes_t dur, unsigned chan_n) { /* this function is never called from a realtime thread, so its OK to block (for short intervals). diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index 5695179863..77e20d59b8 100644 --- a/libs/ardour/midi_port.cc +++ b/libs/ardour/midi_port.cc @@ -130,7 +130,7 @@ MidiPort::flush_buffers (nframes_t nframes, nframes_t offset) void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) { - const Evoral::Event& ev = *i; + const Evoral::Event& ev = *i; // event times should be frames, relative to cycle start assert(ev.time() >= 0); assert(ev.time() < (nframes+offset)); diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index f0c4b2297e..401d67e2ef 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -117,19 +117,19 @@ MidiRegion::~MidiRegion () } nframes_t -MidiRegion::read_at (MidiRingBuffer& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const +MidiRegion::read_at (MidiRingBuffer& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const { return _read_at (_sources, out, position, dur, chan_n, mode); } nframes_t -MidiRegion::master_read_at (MidiRingBuffer& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const +MidiRegion::master_read_at (MidiRingBuffer& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const { return _read_at (_master_sources, out, position, dur, chan_n, mode); } nframes_t -MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const +MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const { /*cerr << "MidiRegion " << _name << "._read_at(" << position << ") - " << position << " duration: " << dur << endl;*/ diff --git a/libs/ardour/midi_ring_buffer.cc b/libs/ardour/midi_ring_buffer.cc index 1f5177614a..cd21905bad 100644 --- a/libs/ardour/midi_ring_buffer.cc +++ b/libs/ardour/midi_ring_buffer.cc @@ -130,7 +130,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes return count; } -template class MidiRingBuffer; +template class MidiRingBuffer; } // namespace ARDOUR diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index 7adb0f177b..4307749e4a 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -51,6 +51,8 @@ MidiSource::MidiSource (Session& s, string name) , _timeline_position(0) , _model(new MidiModel(this)) , _writing (false) + , _model_iter(*_model.get(), 0.0) + , _last_read_end(0) { _read_data_count = 0; _write_data_count = 0; @@ -61,6 +63,8 @@ MidiSource::MidiSource (Session& s, const XMLNode& node) , _timeline_position(0) , _model(new MidiModel(this)) , _writing (false) + , _model_iter(*_model.get(), 0.0) + , _last_read_end(0) { _read_data_count = 0; _write_data_count = 0; @@ -101,13 +105,29 @@ MidiSource::set_state (const XMLNode& node) } nframes_t -MidiSource::midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const +MidiSource::midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const { Glib::Mutex::Lock lm (_lock); if (_model) { - //const size_t n_events = - _model->read(dst, start, cnt, stamp_offset - negative_stamp_offset); - //cout << "Read " << n_events << " events from model." << endl; + Evoral::Sequence::const_iterator& i = _model_iter; + + if (_last_read_end == 0 || start != _last_read_end) { + i = _model->begin(); + cerr << "MidiSource::midi_read seeking to " << start << endl; + while (i != _model->end() && i->time() < start) + ++i; + } + + _last_read_end = start + cnt; + + if (i == _model->end()) { + return cnt; + } + + while (i->time() < start + cnt && i != _model->end()) { + dst.write(i->time(), i->event_type(), i->size(), i->buffer()); + ++i; + } return cnt; } else { return read_unlocked (dst, start, cnt, stamp_offset, negative_stamp_offset); @@ -115,7 +135,7 @@ MidiSource::midi_read (MidiRingBuffer& dst, nframes_t star } nframes_t -MidiSource::midi_write (MidiRingBuffer& dst, nframes_t cnt) +MidiSource::midi_write (MidiRingBuffer& dst, nframes_t cnt) { Glib::Mutex::Lock lm (_lock); return write_unlocked (dst, cnt); diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 6ee1190212..d55226aa69 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -125,9 +125,10 @@ SMFSource::init (string pathstr, bool must_exist) /** All stamps in audio frames */ nframes_t -SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const +SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const { - //cerr << "SMF read_unlocked " << name() << " read " << start << ", count=" << cnt << ", offset=" << stamp_offset << endl; + //cerr << "SMF read_unlocked " << name() << " read " + //<< start << ", count=" << cnt << ", offset=" << stamp_offset << endl; // 64 bits ought to be enough for anybody uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn @@ -191,11 +192,11 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_ /** All stamps in audio frames */ nframes_t -SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt) +SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt) { _write_data_count = 0; - double time; + nframes_t time; Evoral::EventType type; uint32_t size; @@ -233,7 +234,8 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt) ev.set(buf, size, time); ev.set_event_type(EventTypeMap::instance().midi_event_type(ev.buffer()[0])); if (! (ev.is_channel_event() || ev.is_smf_meta_event() || ev.is_sysex()) ) { - cerr << "SMFSource: WARNING: caller tried to write non SMF-Event of type " << std::hex << int(ev.buffer()[0]) << endl; + cerr << "SMFSource: WARNING: caller tried to write non SMF-Event of type " + << std::hex << int(ev.buffer()[0]) << endl; continue; } diff --git a/libs/evoral/evoral/Sequence.hpp b/libs/evoral/evoral/Sequence.hpp index 22f75a74ed..e7a3a3c7b6 100644 --- a/libs/evoral/evoral/Sequence.hpp +++ b/libs/evoral/evoral/Sequence.hpp @@ -80,10 +80,12 @@ public: bool writing() const { return _writing; } void end_write(bool delete_stuck=false); +#if 0 size_t read(EventSink