Use nframes_t for timestamps of real (jack) time MIDI events (i.e. in MidiBuffer...
authorDavid Robillard <d@drobilla.net>
Sun, 15 Feb 2009 01:24:26 +0000 (01:24 +0000)
committerDavid Robillard <d@drobilla.net>
Sun, 15 Feb 2009 01:24:26 +0000 (01:24 +0000)
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

19 files changed:
libs/ardour/ardour/midi_buffer.h
libs/ardour/ardour/midi_diskstream.h
libs/ardour/ardour/midi_playlist.h
libs/ardour/ardour/midi_region.h
libs/ardour/ardour/midi_source.h
libs/ardour/ardour/midi_track.h
libs/ardour/ardour/smf_source.h
libs/ardour/meter.cc
libs/ardour/midi_diskstream.cc
libs/ardour/midi_playlist.cc
libs/ardour/midi_port.cc
libs/ardour/midi_region.cc
libs/ardour/midi_ring_buffer.cc
libs/ardour/midi_source.cc
libs/ardour/smf_source.cc
libs/evoral/evoral/Sequence.hpp
libs/evoral/src/Event.cpp
libs/evoral/src/Sequence.cpp
libs/evoral/test/SequenceTest.cpp

index f90cbfd8e35e82ad2c3774083c47a3d7002ea96e..8ea5e32e81a404a09d18d1bbb010e9ee73287d9c 100644 (file)
@@ -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<TimeType>& 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);
 
index 7a0daf37e8e4f6e24678d53e23ff4384b6074a5b..eddeaa451a9416a45d5f07d0848da25bc43f78f3 100644 (file)
@@ -170,18 +170,16 @@ class MidiDiskstream : public Diskstream
        
        void engage_record_enable ();
        void disengage_record_enable ();
-       void check_note_onoffs(Evoral::MIDIEvent<MidiBuffer::TimeType> &event);
-       void emit_pending_note_offs(MidiBuffer &dst, nframes_t time);
-
-       MidiRingBuffer<MidiBuffer::TimeType>* _playback_buf;
-       MidiRingBuffer<MidiBuffer::TimeType>* _capture_buf;
-       MidiPort*                             _source_port;
-       boost::shared_ptr<SMFSource>          _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<nframes_t>*   _playback_buf;
+       MidiRingBuffer<nframes_t>*   _capture_buf;
+       MidiPort*                    _source_port;
+       boost::shared_ptr<SMFSource> _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 */
index d7fdadb2f532092b129459a374315a4d38c03379..a956878348e771d733671ba281821f8d8877d9d1 100644 (file)
@@ -47,7 +47,7 @@ public:
 
        ~MidiPlaylist ();
 
-       nframes_t read (MidiRingBuffer<double>& buf,
+       nframes_t read (MidiRingBuffer<nframes_t>& buf,
                        nframes_t start, nframes_t cnt, uint32_t chan_n=0);
 
        int set_state (const XMLNode&);
index 781f815ec551582988f91f1951faaf77fd0bcdb2..356e418fc1b113e5e511f1ebe06422faeda5a9de 100644 (file)
@@ -48,8 +48,6 @@ template<typename T> class MidiRingBuffer;
 class MidiRegion : public Region
 {
   public:
-       typedef double TimeType;
-
        ~MidiRegion();
 
        boost::shared_ptr<MidiSource> 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<TimeType>& dst,
+       nframes_t read_at (MidiRingBuffer<nframes_t>& dst,
                           nframes_t position,
                           nframes_t dur, 
                           uint32_t  chan_n = 0,
                           NoteMode  mode = Sustained) const;
 
-       nframes_t master_read_at (MidiRingBuffer<TimeType>& dst,
+       nframes_t master_read_at (MidiRingBuffer<nframes_t>& 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<TimeType>& dst,
+       nframes_t _read_at (const SourceList&, MidiRingBuffer<nframes_t>& dst,
                            nframes_t position,
                            nframes_t dur, 
                            uint32_t chan_n = 0,
index c0b105decd4021955482ae2227708a63ffa91a4a..2126b4b162324740b9844a0c0d27c0573b6282e5 100644 (file)
@@ -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<TimeType>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const;
-       virtual nframes_t midi_write (MidiRingBuffer<TimeType>& src, nframes_t cnt);
+       virtual nframes_t midi_read (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const;
+       virtual nframes_t midi_write (MidiRingBuffer<nframes_t>& src, nframes_t cnt);
 
        virtual void append_event_unlocked(EventTimeUnit unit, const Evoral::Event<TimeType>& 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<TimeType>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const = 0;
-       virtual nframes_t write_unlocked (MidiRingBuffer<TimeType>& dst, nframes_t cnt) = 0;
+       virtual nframes_t read_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const = 0;
+       virtual nframes_t write_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t cnt) = 0;
        
        mutable Glib::Mutex _lock;
        string              _captured_for;
@@ -112,6 +110,9 @@ class MidiSource : public Source
 
        boost::shared_ptr<MidiModel> _model;
        bool                         _writing;
+       
+       mutable Evoral::Sequence<double>::const_iterator _model_iter;
+       mutable nframes_t                                _last_read_end;
 
   private:
        bool file_changed (string path);
index 09c64c29786a056e32598e5302f7d915df7b978d..d4054066f1a546ce553c3f7d5e902399788e7b8e 100644 (file)
@@ -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<double> _immediate_events;
-       NoteMode               _note_mode;
+       MidiRingBuffer<nframes_t> _immediate_events;
+       NoteMode                  _note_mode;
 };
 
 } /* namespace ARDOUR*/
index 9981408abc9d4d9163338612ec3d1a4aadf14437..ccc03acd667102ab61d701336aae19534107b56c 100644 (file)
@@ -102,14 +102,14 @@ class SMFSource : public MidiSource, public Evoral::SMF<double> {
        int init (string idstr, bool must_exist);
 
        nframes_t read_unlocked (
-                       MidiRingBuffer<double>& dst,
+                       MidiRingBuffer<nframes_t>& dst,
                        nframes_t start,
                        nframes_t cn,
                        nframes_t stamp_offset,
                        nframes_t negative_stamp_offset) const;
 
        nframes_t write_unlocked (
-                       MidiRingBuffer<double>& src,
+                       MidiRingBuffer<nframes_t>& src,
                        nframes_t cnt);
 
        bool find (std::string path, bool must_exist, bool& is_new);
index 39d7f63221fee320769122025f1b60f2b97f25dc..31a88b16f0f206bcf121c9b6861bc0679aa6cc45 100644 (file)
@@ -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<double> ev(*i, false);
+                       const Evoral::MIDIEvent<nframes_t> 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);
index af7a5d8873b7ab10968eb5c091b946598abf211e..41f8eb9e196b493b828955892a78a2a8465469d0 100644 (file)
@@ -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<MidiBuffer::TimeType> (size);
-       _capture_buf = new MidiRingBuffer<MidiBuffer::TimeType> (size);
+       _playback_buf = new MidiRingBuffer<nframes_t>(size);
+       _capture_buf = new MidiRingBuffer<nframes_t>(size);
        
        _n_channels = ChanCount(DataType::MIDI, 1);
 
index 7139447a19ba7eb22439a5f362d4c812dd79e0c7..6105e6cfa2b6f16b848a8db0a1cd7a5318dfdce8 100644 (file)
@@ -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<MidiBuffer::TimeType>& dst, nframes_t start,
-                     nframes_t dur, unsigned chan_n)
+MidiPlaylist::read (MidiRingBuffer<nframes_t>& 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).
index 569517986380bd773734a2027c0f45f9048063e3..77e20d59b8174ce9f1ba7c894e7597f49eaca905 100644 (file)
@@ -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<double>& ev = *i;
+                       const Evoral::Event<nframes_t>& ev = *i;
                        // event times should be frames, relative to cycle start
                        assert(ev.time() >= 0);
                        assert(ev.time() < (nframes+offset));
index f0c4b2297eb03ca9ef688e1e667d02e301f65e5e..401d67e2ef9334efdbb4d466048e5cce86415e48 100644 (file)
@@ -117,19 +117,19 @@ MidiRegion::~MidiRegion ()
 }
 
 nframes_t
-MidiRegion::read_at (MidiRingBuffer<TimeType>& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
+MidiRegion::read_at (MidiRingBuffer<nframes_t>& 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<TimeType>& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
+MidiRegion::master_read_at (MidiRingBuffer<nframes_t>& 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<TimeType>& dst, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
+MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer<nframes_t>& dst, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
 {
        /*cerr << "MidiRegion " << _name << "._read_at(" << position << ") - "
                << position << " duration: " << dur << endl;*/
index 1f5177614a8ec7ecdfb43ff35dc099d1e4f973b9..cd21905bad00f625a52345ecc4ec655c1cda7899 100644 (file)
@@ -130,7 +130,7 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
        return count;
 }
 
-template class MidiRingBuffer<double>;
+template class MidiRingBuffer<nframes_t>;
 
 } // namespace ARDOUR
 
index 7adb0f177be3dba47586b320611452eb2630ce7f..4307749e4aa7911bbdfb4e6e4e9ebbde6a54beb7 100644 (file)
@@ -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<MidiBuffer::TimeType>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const
+MidiSource::midi_read (MidiRingBuffer<nframes_t>& 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<double>::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<MidiBuffer::TimeType>& dst, nframes_t star
 }
 
 nframes_t
-MidiSource::midi_write (MidiRingBuffer<MidiBuffer::TimeType>& dst, nframes_t cnt)
+MidiSource::midi_write (MidiRingBuffer<nframes_t>& dst, nframes_t cnt)
 {
        Glib::Mutex::Lock lm (_lock);
        return write_unlocked (dst, cnt);
index 6ee1190212661835b3c12fd851b3a79eb0346b92..d55226aa69f444d962c3af1b02edeac00bf97f34 100644 (file)
@@ -125,9 +125,10 @@ SMFSource::init (string pathstr, bool must_exist)
 
 /** All stamps in audio frames */
 nframes_t
-SMFSource::read_unlocked (MidiRingBuffer<double>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const
+SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& 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<double>& dst, nframes_t start, nframes_
 
 /** All stamps in audio frames */
 nframes_t
-SMFSource::write_unlocked (MidiRingBuffer<double>& src, nframes_t cnt)
+SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& 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<double>& 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;
                }
                
index 22f75a74edc7469eac994e325ca2582d04731388..e7a3a3c7b6b3c02a61e35f99e675c1139a8215f4 100644 (file)
@@ -80,10 +80,12 @@ public:
        bool writing() const { return _writing; }
        void end_write(bool delete_stuck=false);
 
+#if 0
        size_t read(EventSink<Time>& dst,
                    Time             start,
                    Time             length,
                    Time             stamp_offset) const;
+#endif
 
        /** Resizes vector if necessary (NOT realtime safe) */
        void append(const Event<Time>& ev);
@@ -119,9 +121,10 @@ public:
        /** Read iterator */
        class const_iterator {
        public:
+               const_iterator();
                const_iterator(const Sequence<Time>& seq, Time t);
                ~const_iterator();
-
+               
                inline bool valid() const { return !_is_end && _event; }
                inline bool locked() const { return _locked; }
 
@@ -130,6 +133,7 @@ public:
                const boost::shared_ptr< Event<Time> > get_event_pointer() { return _event; }
 
                const const_iterator& operator++(); // prefix only
+
                bool operator==(const const_iterator& other) const;
                bool operator!=(const const_iterator& other) const { return ! operator==(other); }
                
@@ -210,7 +214,7 @@ private:
        ControlLists _dirty_controls;
 
        const   const_iterator _end_iter;
-       mutable Time           _next_read;
+//     mutable Time           _next_read;
        bool                   _percussive;
 
        uint8_t _lowest_note;
index d309d8a0f778e452137033eb2c16ecb9200251e1..dc13a070eedb957f61a57f3566de023a40091631 100644 (file)
@@ -68,6 +68,7 @@ Event<Timestamp>::~Event() {
 #endif // EVORAL_EVENT_ALLOC
 
 template class Event<double>;
+template class Event<uint32_t>;
 
 } // namespace Evoral
 
index cec549562945a8eebd2fdc499095787f19ba3c50..f642e9acb338e9ac7e6dbc3a1921c97e0ca12d14 100644 (file)
@@ -69,6 +69,15 @@ static ostream& errorout = cerr;
 
 // Read iterator (const_iterator)
 
+template<typename Time>
+Sequence<Time>::const_iterator::const_iterator()
+       : _seq(NULL)
+       , _is_end(true)
+       , _locked(false)
+{
+       _event = boost::shared_ptr< Event<Time> >(new Event<Time>());
+}
+
 template<typename Time>
 Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>& seq, Time t)
        : _seq(&seq)
@@ -395,8 +404,13 @@ template<typename Time>
 typename Sequence<Time>::const_iterator&
 Sequence<Time>::const_iterator::operator=(const const_iterator& other)
 {
-       if (_locked && _seq != other._seq) {
-               _seq->read_unlock();
+       if (_seq != other._seq) {
+               if (_locked) {
+                       _seq->read_unlock();
+               }
+               if (other._locked) {
+                  other._seq->read_lock();
+               }
        }
 
        _seq           = other._seq;
@@ -434,7 +448,7 @@ Sequence<Time>::Sequence(const TypeMap& type_map, size_t size)
        , _notes(size)
        , _writing(false)
        , _end_iter(*this, DBL_MAX)
-       , _next_read(UINT32_MAX)
+//     , _next_read(UINT32_MAX)
        , _percussive(false)
        , _lowest_note(127)
        , _highest_note(0)
@@ -446,6 +460,7 @@ Sequence<Time>::Sequence(const TypeMap& type_map, size_t size)
        assert( ! _end_iter._locked);
 }
 
+#if 0
 /** Read events in frame range \a start .. \a (start + dur) into \a dst,
  * adding \a offset to each event's timestamp.
  * \return number of events written to \a dst
@@ -497,6 +512,7 @@ Sequence<Time>::read(EventSink<Time>& dst, Time start, Time dur, Time offset) co
 
        return read_events;
 }
+#endif
 
 /** Write the controller event pointed to by \a iter to \a ev.
  * The buffer of \a ev will be allocated or resized as necessary.
@@ -582,7 +598,7 @@ Sequence<Time>::clear()
        _notes.clear();
        for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li)
                li->second->list()->clear();
-       _next_read = 0;
+//     _next_read = 0;
        _read_iter = end();
        _lock.writer_unlock();
 }
index 7da171d10dc56e37e4dc11f5f1c9c79859555bad..96cb3221bf2069c879c4c703f76b81697b6f03d0 100644 (file)
@@ -54,8 +54,11 @@ SequenceTest::preserveEventOrderingTest (void)
        TestSink<Time> sink;
        sink.writing.connect(sigc::mem_fun(&sink, &TestSink<Time>::assertLastEventTimeEarlier));
 
-       seq->read(sink, 0, 1200, 0);
+
+       for (MySequence<Time>::const_iterator i = seq->begin(); i != seq->end(); ++i) {
+               sink.write(i->time(), i->event_type(), i->size(), i->buffer());
+       }
        
        CPPUNIT_ASSERT_EQUAL(size_t(12), test_notes.size());
-       
 }
+