do not allow smf_source's reads to stomp on cached read_end position in parent class, which creates chaos by being out of sync with MidiSource::_model_iterator. this doesn't totally fix MIDI playback, but it helps

git-svn-id: svn://localhost/ardour2/branches/3.0@5665 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2009-09-16 01:08:51 +00:00
parent 127b8a62b7
commit fa4e858eb3
12 changed files with 121 additions and 39 deletions

View File

@ -51,6 +51,7 @@ public:
inline bool read_contents(uint32_t size, uint8_t* buf);
size_t read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset=0);
void dump(std::ostream& dst);
/** Set the channel filtering mode.
* @param mask If mode is FilterChannels, each bit represents a midi channel:

View File

@ -85,6 +85,7 @@ private:
double _last_ev_time_beats;
sframes_t _last_ev_time_frames;
mutable sframes_t _smf_last_read_end;
};
}; /* namespace ARDOUR */

View File

@ -93,7 +93,6 @@ MidiBuffer::read_from (const Buffer& src, nframes_t nframes, nframes_t dst_offse
const Evoral::MIDIEvent<TimeType> ev(*i, false);
if (ev.time() >= src_offset && ev.time() < (nframes+src_offset)) {
push_back (ev);
cerr << "got note " << ev << endl;
}
}

View File

@ -858,8 +858,6 @@ MidiDiskstream::can_internal_playback_seek (nframes_t distance)
int
MidiDiskstream::internal_playback_seek (nframes_t distance)
{
cerr << "MDS: internal_playback_seek " << distance << endl;
first_recordable_frame += distance;
playback_sample += distance;
@ -929,8 +927,7 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
_id, this_read, start) << endmsg;
return -1;
}
//cout << "MDS this read " << this_read << " start = " << start << endl;
g_atomic_int_add(&_frames_written_to_ringbuffer, this_read);
_read_data_count = _playlist->read_data_count();
@ -1650,7 +1647,9 @@ MidiDiskstream::get_playback (MidiBuffer& dst, nframes_t start, nframes_t end)
// Translates stamps to be relative to start
_playback_buf->read(dst, start, end);
#if 0
const size_t events_read = _playback_buf->read(dst, start, end);
cout << _name << ": MDS events read = " << events_read

View File

@ -91,7 +91,7 @@ MidiPlaylist::MidiPlaylist (boost::shared_ptr<const MidiPlaylist> other, string
out_o++;
out_n++;
}
// cerr << "HUH!? second region in the crossfade not found!" << endl;
// cerr << "HUH!? second region in the crossfade not found!" << endl;
}
}

View File

@ -147,7 +147,7 @@ MidiRegion::_read_at (const SourceList& /*srcs*/, MidiRingBuffer<nframes_t>& dst
nframes_t internal_offset = 0;
nframes_t src_offset = 0;
nframes_t to_read = 0;
/* precondition: caller has verified that we cover the desired section */
assert(chan_n == 0);
@ -191,7 +191,16 @@ MidiRegion::_read_at (const SourceList& /*srcs*/, MidiRingBuffer<nframes_t>& dst
// _start from the note times in the midi source
negative_output_buffer_position = _start;
}
#if 0
cerr << "\t\tsource read from " << _position << " - " << _start << " (" << _position - _start << ") "
<< " start in source " << _start << " + " << internal_offset << " (" << _start + internal_offset << ") "
<< " dur = " << to_read
<< " offset = " << output_buffer_position
<< " negoffset = " << negative_output_buffer_position
<< endl;
#endif
if (src->midi_read (
dst, // destination buffer
_position - _start, // start position of the source in this read context

View File

@ -43,17 +43,15 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
size_t count = 0;
//cerr << "MRB read " << start << " .. " << end << " + " << offset << endl;
while (this->read_space() >= sizeof(T) + sizeof(Evoral::EventType) + sizeof(uint32_t)) {
this->full_peek(sizeof(T), (uint8_t*)&ev_time);
if (ev_time > end) {
//cerr << "MRB event @ " << ev_time << " past end @ " << end << endl;
// cerr << "MRB event @ " << ev_time << " past end @ " << end << endl;
break;
} else if (ev_time < start) {
//cerr << "MRB event @ " << ev_time << " before start @ " << start << endl;
// cerr << "MRB event @ " << ev_time << " before start @ " << start << endl;
break;
}
@ -67,7 +65,7 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
if (ev_type == LoopEventType) {
/*ev_time -= start;
ev_time += offset;*/
cerr << "MRB loop boundary @ " << ev_time << endl;
// cerr << "MRB loop boundary @ " << ev_time << endl;
// Return without reading data or writing to buffer (loop events have no data)
// FIXME: This is not correct, loses events after the loop this cycle
@ -87,11 +85,7 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
continue;
}
}
/*cerr << "MRB " << this << " - Reading event, time = "
<< ev_time << " - " << start << " => " << ev_time - start
<< ", size = " << ev_size << endl;*/
assert(ev_time >= start);
ev_time -= start;
ev_time += offset;
@ -126,6 +120,84 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
return count;
}
template<typename T>
void
MidiRingBuffer<T>::dump(ostream& str)
{
size_t rspace;
if ((rspace = this->read_space()) == 0) {
str << "MRB::dump: empty\n";
return;
}
T ev_time;
Evoral::EventType ev_type;
uint32_t ev_size;
size_t read_ptr = g_atomic_int_get (&this->_read_ptr);
str << "Dump @ " << read_ptr << endl;
while (1) {
uint8_t* wp;
uint8_t* data;
size_t write_ptr;
#define space(r,w) ((w > r) ? (w - r) : ((w - r + this->_size) % this->_size))
write_ptr = g_atomic_int_get (&this->_write_ptr);
if (space (read_ptr, write_ptr) < sizeof (T)) {
break;
}
wp = &this->_buf[read_ptr];
memcpy (&ev_time, wp, sizeof (T));
read_ptr = (read_ptr + sizeof (T)) % this->_size;
str << "time " << ev_time;
write_ptr = g_atomic_int_get (&this->_write_ptr);
if (space (read_ptr, write_ptr) < sizeof (ev_type)) {
break;
}
wp = &this->_buf[read_ptr];
memcpy (&ev_type, wp, sizeof (ev_type));
read_ptr = (read_ptr + sizeof (ev_type)) % this->_size;
str << " type " << ev_type;
write_ptr = g_atomic_int_get (&this->_write_ptr);
if (space (read_ptr, write_ptr) < sizeof (ev_size)) {
str << "!OUT!\n";
break;
}
wp = &this->_buf[read_ptr];
memcpy (&ev_size, wp, sizeof (ev_size));
read_ptr = (read_ptr + sizeof (ev_size)) % this->_size;
str << " size " << ev_size;
write_ptr = g_atomic_int_get (&this->_write_ptr);
if (space (read_ptr, write_ptr) < ev_size) {
str << "!OUT!\n";
break;
}
data = new uint8_t[ev_size];
wp = &this->_buf[read_ptr];
memcpy (data, wp, ev_size);
read_ptr = (read_ptr + ev_size) % this->_size;
for (uint32_t i = 0; i != ev_size; ++i) {
str << ' ' << hex << (int) data[i] << dec;
}
str << endl;
delete [] data;
}
}
template class MidiRingBuffer<nframes_t>;

View File

@ -137,16 +137,15 @@ MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, sframes_t source_start,
#define BEATS_TO_FRAMES(t) (converter.to(t) + stamp_offset - negative_stamp_offset)
Evoral::Sequence<double>::const_iterator& i = _model_iter;
if (_last_read_end == 0 || start != _last_read_end) { // || !i.valid()) {
//cerr << "MidiSource seeking to " << start << " from " << _last_read_end << endl;
if (_last_read_end == 0 || start != _last_read_end || !i.valid()) {
for (i = _model->begin(); i != _model->end(); ++i) {
if (BEATS_TO_FRAMES(i->time()) >= start) {
break;
}
}
}
_last_read_end = start + cnt;
for (; i != _model->end(); ++i) {
@ -234,7 +233,7 @@ MidiSource::session_saved()
stringstream ss(basename.substr(last_dash+1));
unsigned write_count = 0;
ss >> write_count;
cerr << "WRITE COUNT: " << write_count << endl;
// cerr << "WRITE COUNT: " << write_count << endl;
++write_count; // start at 1
ss.clear();
ss << basename.substr(0, last_dash) << "-" << write_count;

View File

@ -55,6 +55,7 @@ SMFSource::SMFSource (Session& s, const ustring& path, bool embedded, Source::Fl
, Evoral::SMF()
, _last_ev_time_beats(0.0)
, _last_ev_time_frames(0)
, _smf_last_read_end (0)
{
if (init(_name, false)) {
throw failed_constructor ();
@ -72,6 +73,7 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
, FileSource(s, node, must_exist)
, _last_ev_time_beats(0.0)
, _last_ev_time_frames(0)
, _smf_last_read_end (0)
{
if (set_state(node)) {
throw failed_constructor ();
@ -116,20 +118,20 @@ SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& destination, sframes_t sour
const uint64_t start_ticks = (uint64_t)(converter.from(start) * ppqn());
if (_last_read_end == 0 || start != _last_read_end) {
if (_smf_last_read_end == 0 || start != _smf_last_read_end) {
//cerr << "SMFSource::read_unlocked seeking to " << start << endl;
Evoral::SMF::seek_to_start();
while (time < start_ticks) {
ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);
if (ret == -1) { // EOF
_last_read_end = start + duration;
_smf_last_read_end = start + duration;
return duration;
}
time += ev_delta_t; // accumulate delta time
}
}
_last_read_end = start + duration;
_smf_last_read_end = start + duration;
while (true) {
ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);

View File

@ -199,12 +199,12 @@ protected:
template<typename Time>
std::ostream& operator<<(std::ostream& o, const Evoral::Event<Time>& ev) {
o << "Event type = " << ev.event_type() << " @ " << " @ " << ev.time() << "\n\t";
o << "Event type = " << ev.event_type() << " @ " << ev.time();
o << std::hex;
for (uint32_t n = 0; n < ev.size(); ++n) {
o << (int) ev.buffer()[n] << ' ';
o << ' ' << (int) ev.buffer()[n];
}
o << std::dec << std::endl;
o << std::dec;
return o;
}

View File

@ -205,10 +205,10 @@ SMF::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const
assert(midi_event_is_valid(*buf, *size));
/*printf("SMF::read_event:\n");
/* printf("SMF::read_event @ %u: ", *delta_t);
for (size_t i = 0; i < *size; ++i) {
printf("%X ", (*buf)[i]);
} printf("\n");*/
} printf("\n") */
return event_size;
} else {
@ -223,10 +223,10 @@ SMF::append_event_delta(uint32_t delta_t, uint32_t size, const uint8_t* buf)
return;
}
/*printf("SMF::append_event_delta:\n");
/* printf("SMF::append_event_delta @ %u:", delta_t);
for (size_t i = 0; i < size; ++i) {
printf("%X ", buf[i]);
} printf("\n");*/
} printf("\n"); */
if (!midi_event_is_valid(buf, size)) {
cerr << "WARNING: SMF ignoring illegal MIDI event" << endl;

View File

@ -33,7 +33,7 @@
#include "evoral/TypeMap.hpp"
#include "evoral/midi_util.h"
//#define DEBUG_SEQUENCE 1
// #define DEBUG_SEQUENCE 1
#ifdef DEBUG_SEQUENCE
#include <boost/format.hpp>
using boost::format;
@ -209,10 +209,10 @@ Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>& seq, Time t
_locked = false;
_seq->read_unlock();
} else {
DUMP(format("New iterator = %1% : %2% @ %3%\n")
% (int)_event->event_type()
% (int)((MIDIEvent<Time>*)_event.get())->type()
% _event->time());
DUMP(printf("New iterator = 0x%x : 0x%x @ %f\n",
(int)_event->event_type(),
(int)((MIDIEvent<Time>*)_event.get())->type(),
_event->time()));
assert(midi_event_is_valid(_event->buffer(), _event->size()));
}
}