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:
parent
127b8a62b7
commit
fa4e858eb3
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user