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); void midi_panic(void);
bool write_immediate_event (Evoral::EventType event_type, size_t size, const uint8_t* buf); 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; } 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; MonitorState get_input_monitoring_state (bool recording, bool talkback) const;
MidiBuffer const& immediate_event_buffer () const { return _immediate_event_buffer; } 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>& immediate_events () { return _immediate_events; }
MidiRingBuffer<samplepos_t>& user_immediate_events () { return _user_immediate_events; }
void set_input_active (bool); void set_input_active (bool);
bool input_active () const; bool input_active () const;
@ -160,7 +163,9 @@ protected:
private: private:
MidiRingBuffer<samplepos_t> _immediate_events; MidiRingBuffer<samplepos_t> _immediate_events;
MidiRingBuffer<samplepos_t> _user_immediate_events;
MidiBuffer _immediate_event_buffer; MidiBuffer _immediate_event_buffer;
MidiBuffer _user_immediate_event_buffer;
MidiRingBuffer<samplepos_t> _step_edit_ring_buffer; MidiRingBuffer<samplepos_t> _step_edit_ring_buffer;
NoteMode _note_mode; NoteMode _note_mode;
bool _step_editing; bool _step_editing;

View File

@ -572,8 +572,8 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
/* AUDIO */ /* AUDIO */
const size_t n_buffers = bufs.count().n_audio(); const size_t n_buffers = bufs.count().n_audio();
uint32_t n = 0; uint32_t n = 0;
for (auto const& chaninfo : *c) { for (auto const& chaninfo : *c) {
AudioBuffer& buf (bufs.get_audio (n%n_buffers)); AudioBuffer& buf (bufs.get_audio (n%n_buffers));
++n; ++n;
@ -611,6 +611,8 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
/* MIDI */ /* MIDI */
uint32_t cnt = 0;
if (_midi_buf) { if (_midi_buf) {
// Pump entire port buffer into the ring buffer (TODO: split cycles?) // 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; bool skip_event = false;
if (mt) { 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()); MidiBuffer const& ieb (mt->immediate_event_buffer());
for (MidiBuffer::const_iterator j = ieb.begin(); j != ieb.end(); ++j) { for (MidiBuffer::const_iterator j = ieb.begin(); j != ieb.end(); ++j) {
if (*j == ev) { 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())) { if (!filter || !filter->filter(ev.buffer(), ev.size())) {
_midi_buf->write (event_time, ev.event_type(), ev.size(), ev.buffer()); _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 */ DataRecorded (_midi_write_source); /* EMIT SIGNAL */
} }
} }

View File

@ -82,7 +82,9 @@ using namespace PBD;
MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode) MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
: Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI) : Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
, _immediate_events(6096) // FIXME: size? , _immediate_events(6096) // FIXME: size?
, _user_immediate_events(2048) // FIXME: size?
, _immediate_event_buffer(6096) , _immediate_event_buffer(6096)
, _user_immediate_event_buffer(2048)
, _step_edit_ring_buffer(64) // FIXME: size? , _step_edit_ring_buffer(64) // FIXME: size?
, _note_mode (Sustained) , _note_mode (Sustained)
, _step_editing (false) , _step_editing (false)
@ -502,7 +504,7 @@ MidiTrack::snapshot_out_of_band_data (samplecnt_t nframes)
{ {
_immediate_event_buffer.clear (); _immediate_event_buffer.clear ();
if (0 == _immediate_events.read_space()) { if (0 == _immediate_events.read_space()) {
return; goto user;
} }
assert (nframes > 0); 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); _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 void
@ -526,6 +550,7 @@ MidiTrack::write_out_of_band_data (BufferSet& bufs, samplecnt_t nframes) const
{ {
MidiBuffer& buf (bufs.get_midi (0)); MidiBuffer& buf (bufs.get_midi (0));
buf.merge_from (_immediate_event_buffer, nframes); buf.merge_from (_immediate_event_buffer, nframes);
buf.merge_from (_user_immediate_event_buffer, nframes);
} }
int 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); 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 void
MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state) MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
{ {
@ -952,6 +987,7 @@ MidiTrack::realtime_handle_transport_stopped ()
{ {
Route::realtime_handle_transport_stopped (); Route::realtime_handle_transport_stopped ();
_disk_reader->resolve_tracker (_immediate_events, 0); _disk_reader->resolve_tracker (_immediate_events, 0);
_disk_reader->resolve_tracker (_user_immediate_events, 0);
} }
void void