13
0

MIDI tracks: split immediate events into ardour- and user-generated

This now allows the already-apparently possible recording of user-input from the kbd
in the MIDI track header to actually be successful
This commit is contained in:
Paul Davis 2023-09-13 23:57:49 -06:00
parent a2656d6612
commit d44c9787b6
3 changed files with 53 additions and 3 deletions

View File

@ -75,6 +75,7 @@ public:
void midi_panic(void);
bool write_immediate_event (Evoral::EventType event_type, size_t size, const uint8_t* buf);
bool write_user_immediate_event (Evoral::EventType event_type, size_t size, const uint8_t* buf);
std::shared_ptr<VelocityControl> velocity_control() const { return _velocity_control; }
@ -135,7 +136,9 @@ public:
MonitorState get_input_monitoring_state (bool recording, bool talkback) const;
MidiBuffer const& immediate_event_buffer () const { return _immediate_event_buffer; }
MidiBuffer const& user_immediate_event_buffer () const { return _user_immediate_event_buffer; }
MidiRingBuffer<samplepos_t>& immediate_events () { return _immediate_events; }
MidiRingBuffer<samplepos_t>& user_immediate_events () { return _user_immediate_events; }
void set_input_active (bool);
bool input_active () const;
@ -160,7 +163,9 @@ protected:
private:
MidiRingBuffer<samplepos_t> _immediate_events;
MidiRingBuffer<samplepos_t> _user_immediate_events;
MidiBuffer _immediate_event_buffer;
MidiBuffer _user_immediate_event_buffer;
MidiRingBuffer<samplepos_t> _step_edit_ring_buffer;
NoteMode _note_mode;
bool _step_editing;

View File

@ -572,8 +572,8 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
/* AUDIO */
const size_t n_buffers = bufs.count().n_audio();
uint32_t n = 0;
for (auto const& chaninfo : *c) {
AudioBuffer& buf (bufs.get_audio (n%n_buffers));
++n;
@ -611,6 +611,8 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
/* MIDI */
uint32_t cnt = 0;
if (_midi_buf) {
// Pump entire port buffer into the ring buffer (TODO: split cycles?)
@ -658,7 +660,10 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
bool skip_event = false;
if (mt) {
/* skip injected immediate/out-of-band events */
/* skip injected immediate/out-of-band
* events, but allow those from
* user_immediate_event_buffer
*/
MidiBuffer const& ieb (mt->immediate_event_buffer());
for (MidiBuffer::const_iterator j = ieb.begin(); j != ieb.end(); ++j) {
if (*j == ev) {
@ -672,6 +677,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
if (!filter || !filter->filter(ev.buffer(), ev.size())) {
_midi_buf->write (event_time, ev.event_type(), ev.size(), ev.buffer());
cnt++;
}
}
@ -697,6 +703,9 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
}
}
}
if (cnt) {
DataRecorded (_midi_write_source); /* EMIT SIGNAL */
}
}

View File

@ -82,7 +82,9 @@ using namespace PBD;
MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
: Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
, _immediate_events(6096) // FIXME: size?
, _user_immediate_events(2048) // FIXME: size?
, _immediate_event_buffer(6096)
, _user_immediate_event_buffer(2048)
, _step_edit_ring_buffer(64) // FIXME: size?
, _note_mode (Sustained)
, _step_editing (false)
@ -502,7 +504,7 @@ MidiTrack::snapshot_out_of_band_data (samplecnt_t nframes)
{
_immediate_event_buffer.clear ();
if (0 == _immediate_events.read_space()) {
return;
goto user;
}
assert (nframes > 0);
@ -519,6 +521,28 @@ MidiTrack::snapshot_out_of_band_data (samplecnt_t nframes)
*/
_immediate_events.read (_immediate_event_buffer, 0, 1, nframes - 1, true);
user:
_user_immediate_event_buffer.clear ();
if (0 == _user_immediate_events.read_space()) {
return;
}
assert (nframes > 0);
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of user immediate events to deliver\n", name(), _user_immediate_events.read_space()));
/* write as many of the user immediate events as we can, but give "true" as
* the last argument ("stop on overflow in destination") so that we'll
* ship the rest out next time.
*
* the (nframes-1) argument puts all these events at the last
* possible position of the output buffer, so that we do not
* violate monotonicity when writing.
*/
_user_immediate_events.read (_user_immediate_event_buffer, 0, 1, nframes - 1, true);
}
void
@ -526,6 +550,7 @@ MidiTrack::write_out_of_band_data (BufferSet& bufs, samplecnt_t nframes) const
{
MidiBuffer& buf (bufs.get_midi (0));
buf.merge_from (_immediate_event_buffer, nframes);
buf.merge_from (_user_immediate_event_buffer, nframes);
}
int
@ -650,6 +675,16 @@ MidiTrack::write_immediate_event(Evoral::EventType event_type, size_t size, cons
return (_immediate_events.write (0, event_type, size, buf) == size);
}
bool
MidiTrack::write_user_immediate_event(Evoral::EventType event_type, size_t size, const uint8_t* buf)
{
if (!Evoral::midi_event_is_valid(buf, size)) {
cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
return false;
}
return (_user_immediate_events.write (0, event_type, size, buf) == size);
}
void
MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
{
@ -952,6 +987,7 @@ MidiTrack::realtime_handle_transport_stopped ()
{
Route::realtime_handle_transport_stopped ();
_disk_reader->resolve_tracker (_immediate_events, 0);
_disk_reader->resolve_tracker (_user_immediate_events, 0);
}
void