Fix MIDI playback.

git-svn-id: svn://localhost/ardour2/branches/3.0@5024 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2009-05-01 17:32:48 +00:00
parent 3014d23801
commit 848df74e58
9 changed files with 38 additions and 57 deletions

View file

@ -128,7 +128,7 @@ class MidiDiskstream : public Diskstream
void non_realtime_input_change ();
void non_realtime_locate (nframes_t location);
static void set_readahed_frames( nframes_t frames_ahead ) { midi_readahead = frames_ahead; }
static void set_readahead_frames(nframes_t frames_ahead) { midi_readahead = frames_ahead; }
protected:
int seek (nframes_t which_sample, bool complete_refill = false);

View file

@ -652,8 +652,8 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
chaninfo->current_capture_buffer = chaninfo->capture_vector.buf[0];
/* note: grab the entire port buffer, but only copy what we were supposed to for recording, and use
rec_offset
/* note: grab the entire port buffer, but only copy what we were supposed to
for recording, and use rec_offset
*/
AudioPort* const ap = _io->audio_input(n);

View file

@ -111,10 +111,8 @@ bool
MidiBuffer::push_back(const Evoral::MIDIEvent<TimeType>& ev)
{
const size_t stamp_size = sizeof(TimeType);
/*cerr << "MidiBuffer: pushing event " << " size: " << _size
<< " event size: " << ev.size()
<< " capacity: " << _capacity
<< " stamp size: " << stamp_size << " \n";*/
/*cerr << "MidiBuffer: pushing event @ " << ev.time()
<< " size = " << ev.size() << endl;*/
if (_size + stamp_size + ev.size() >= _capacity) {
cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;

View file

@ -542,10 +542,8 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_
/* data will be written to disk */
if (rec_nframes == nframes && rec_offset == 0) {
playback_distance = nframes;
} else {
collect_playback = true;
}
@ -615,20 +613,15 @@ MidiDiskstream::commit (nframes_t nframes)
adjust_capture_position = 0;
}
/* what audio does:
* can't do this with midi: write space is in bytes, chunk_frames is in frames
if (_slaved) {
need_butler = _playback_buf->write_space() >= _playback_buf->capacity() / 2;
} else {
need_butler = _playback_buf->write_space() >= disk_io_chunk_frames
|| _capture_buf->read_space() >= disk_io_chunk_frames;
}*/
// Use The Counters To calculate how much time the Ringbuffer holds.
uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
if ((frames_written - frames_read) <= midi_readahead)
if ((frames_written - frames_read) + nframes < midi_readahead) {
need_butler = true;
}
/*cerr << "MDS written: " << frames_written << " - read: " << frames_read <<
" = " << frames_written - frames_read
<< " + " << nframes << " < " << midi_readahead << " = " << need_butler << ")" << endl;*/
if (commit_should_unlock) {
state_lock.unlock();
@ -687,11 +680,7 @@ MidiDiskstream::can_internal_playback_seek (nframes_t distance)
{
uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
if ((frames_written-frames_read) < distance) {
return false;
} else {
return true;
}
return ((frames_written - frames_read) < distance);
}
int
@ -763,11 +752,13 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
this_read = min(dur,this_read);
if (midi_playlist()->read (*_playback_buf, start, this_read) != this_read) {
error << string_compose(_("MidiDiskstream %1: cannot read %2 from playlist at frame %3"), _id, this_read,
start) << endmsg;
error << string_compose(
_("MidiDiskstream %1: cannot read %2 from playlist at frame %3"),
_id, this_read, start) << endmsg;
return -1;
}
//cout << "this write " << this_read << "start= " << start << endl;
//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();
@ -775,7 +766,7 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
if (reversed) {
// Swap note ons with note offs here. etc?
// Fully reversing MIDI required look-ahead (well, behind) to find previous
// Fully reversing MIDI requires look-ahead (well, behind) to find previous
// CC values etc. hard.
} else {
@ -837,13 +828,14 @@ MidiDiskstream::do_refill ()
uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
if ((frames_written - frames_read) >= midi_readahead) {
//cout << "Nothing to do. all fine" << endl;
//cout << "MDS Nothing to do. all fine" << endl;
return 0;
}
nframes_t to_read = midi_readahead - (frames_written - frames_read);
//cout << "read for midi_readahead " << to_read << " rb_contains: " << frames_written-frames_read << endl;
//cout << "MDS read for midi_readahead " << to_read << " rb_contains: "
// << frames_written - frames_read << endl;
to_read = min(to_read, (max_frames - file_frame));
@ -1494,8 +1486,8 @@ MidiDiskstream::get_playback (MidiBuffer& dst, nframes_t start, nframes_t end)
_playback_buf->read(dst, start, end);
#else
const size_t events_read = _playback_buf->read(dst, start, end);
cout << "frames read = " << frames_read << " events read = " << events_read
<< " end = " << end << " start = " << start
cout << "MDS events read = " << events_read
<< " start = " << start << " end = " << end
<< " readspace " << _playback_buf->read_space()
<< " writespace " << _playback_buf->write_space() << endl;
#endif

View file

@ -140,7 +140,6 @@ MidiPlaylist::read (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t d
vector<boost::shared_ptr<Region> > regs;
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
if ((*i)->coverage (start, end) != OverlapNone) {
regs.push_back(*i);
}
@ -150,7 +149,6 @@ MidiPlaylist::read (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t d
sort(regs.begin(), regs.end(), layer_cmp);
for (vector<boost::shared_ptr<Region> >::iterator i = regs.begin(); i != regs.end(); ++i) {
// FIXME: ensure time is monotonic here?
boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(*i);
if (mr) {
mr->read_at (dst, start, dur, chan_n, _note_mode);

View file

@ -144,9 +144,6 @@ MidiRegion::master_read_at (MidiRingBuffer<nframes_t>& out, sframes_t position,
nframes_t
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;*/
nframes_t internal_offset = 0;
nframes_t src_offset = 0;
nframes_t to_read = 0;
@ -168,7 +165,6 @@ MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer<nframes_t>& dst, nf
return 0; /* read nothing */
}
if ((to_read = min (dur, _length - internal_offset)) == 0) {
return 0; /* read nothing */
}
@ -199,7 +195,7 @@ MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer<nframes_t>& dst, nf
if (src->midi_read (
dst, // destination buffer
_position - _start, // start position of the source in this read context
_start + internal_offset, // where to start reading in the region
_start + internal_offset, // where to start reading in the source
to_read, // read duration in frames
output_buffer_position, // the offset in the output buffer
negative_output_buffer_position // amount to substract from note times

View file

@ -50,10 +50,10 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
this->full_peek(sizeof(T), (uint8_t*)&ev_time);
if (ev_time > end) {
//cerr << "MRB: PAST END (" << ev_time << " : " << end << ")" << endl;
//cerr << "MRB event @ " << ev_time << " past end @ " << end << endl;
break;
} else if (ev_time < start) {
//cerr << "MRB (start " << start << ") - Skipping event at (too early) time " << ev_time << endl;
//cerr << "MRB event @ " << ev_time << " before start @ " << start << endl;
break;
}
@ -63,8 +63,7 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
continue;
}
// This event marks a loop happening. this means that
// the next events timestamp will be non-monotonic.
// This event marks a loop end (i.e. the next event's timestamp will be non-monotonic)
if (ev_type == LoopEventType) {
ev_time -= start;
ev_time += offset;
@ -73,6 +72,7 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
// We can safely return, without reading the data, because
// a LoopEvent does not have data.
cerr << "MRB loop boundary @ " << ev_time << endl;
return count + 1;
}
@ -90,9 +90,9 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
}
}
//cerr << "MRB " << this << " - Reading event, time = "
// << ev_time << " - " << start << " => " << ev_time - start
// << ", size = " << ev_size << endl;
/*cerr << "MRB " << this << " - Reading event, time = "
<< ev_time << " - " << start << " => " << ev_time - start
<< ", size = " << ev_size << endl;*/
assert(ev_time >= start);
ev_time -= start;
@ -119,14 +119,11 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
write_loc[0] = (write_loc[0] & 0xF0) | (get_channel_mask() & 0x0F);
}
++count;
//cerr << "MRB - read event at time " << ev_time << endl;
} else {
cerr << "WARNING: error reading event contents from MIDI ring" << endl;
}
}
//cerr << "MTB read space: " << read_space() << endl;
return count;
}

View file

@ -138,7 +138,7 @@ MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, sframes_t source_start,
Evoral::Sequence<double>::const_iterator& i = _model_iter;
if (_last_read_end == 0 || start != _last_read_end || !i.valid()) {
if (_last_read_end == 0 || start != _last_read_end) { // || !i.valid()) {
cerr << "MidiSource seeking to " << start << " from " << _last_read_end << endl;
for (i = _model->begin(); i != _model->end(); ++i) {
if (BEATS_TO_FRAMES(i->time()) >= start) {
@ -150,8 +150,8 @@ MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, sframes_t source_start,
_last_read_end = start + cnt;
for (; i != _model->end(); ++i) {
const nframes_t time_frames = BEATS_TO_FRAMES(i->time());
if (time_frames < start + cnt) {
const sframes_t time_frames = BEATS_TO_FRAMES(i->time());
if (time_frames < source_start + start + cnt) {
dst.write(time_frames, i->event_type(), i->size(), i->buffer());
} else {
break;

View file

@ -78,7 +78,7 @@ Session::start_butler_thread ()
* (i.e. how many MIDI bytes we might see in a cycle)
*/
midi_dstream_buffer_size = (uint32_t) floor (Config->get_midi_track_buffer_seconds() * (float)frame_rate());
MidiDiskstream::set_readahed_frames ((nframes_t) (Config->get_midi_readahead() * (float) frame_rate()));
MidiDiskstream::set_readahead_frames ((nframes_t) (Config->get_midi_readahead() * (float) frame_rate()));
Crossfade::set_buffer_size (audio_dstream_buffer_size);