class MidiBuffer : public Buffer
{
public:
- typedef double TimeType;
+ typedef nframes_t TimeType;
MidiBuffer(size_t capacity);
~MidiBuffer();
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);
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 */
~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&);
class MidiRegion : public Region
{
public:
- typedef double TimeType;
-
~MidiRegion();
boost::shared_ptr<MidiSource> midi_source (uint32_t n=0) const;
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,
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,
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;
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;
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);
void set_note_mode (NoteMode m);
protected:
-
XMLNode& state (bool full);
int _set_state (const XMLNode&, bool call_base);
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*/
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);
// 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);
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);
/** 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).
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));
}
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;*/
return count;
}
-template class MidiRingBuffer<double>;
+template class MidiRingBuffer<nframes_t>;
} // namespace ARDOUR
, _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;
, _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;
}
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);
}
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);
/** 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
/** 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;
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;
}
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);
/** 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; }
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); }
ControlLists _dirty_controls;
const const_iterator _end_iter;
- mutable Time _next_read;
+// mutable Time _next_read;
bool _percussive;
uint8_t _lowest_note;
#endif // EVORAL_EVENT_ALLOC
template class Event<double>;
+template class Event<uint32_t>;
} // namespace Evoral
// 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)
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;
, _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)
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
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.
_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();
}
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());
-
}
+