13
0

preparations for clip data display (MIDI) while recording

This commit is contained in:
Paul Davis 2024-10-10 22:18:09 -06:00
parent c03c3dd918
commit 7c944687c9
2 changed files with 59 additions and 18 deletions

View File

@ -45,6 +45,7 @@
#include "evoral/PatchChange.h"
#include "evoral/SMF.h"
#include "ardour/event_ring_buffer.h"
#include "ardour/midi_model.h"
#include "ardour/midi_state_tracker.h"
#include "ardour/processor.h"
@ -777,8 +778,10 @@ struct SlotArmInfo {
~SlotArmInfo();
Trigger& slot;
Temporal::timepos_t start;
Temporal::timepos_t end;
Temporal::Beats start_beats;
samplepos_t start_samples;
Temporal::Beats end_beats;
samplepos_t end_samples;
RTMidiBufferBeats* midi_buf;
AudioTrigger::AudioData audio_buf;
RubberBand::RubberBandStretcher* stretcher;
@ -931,8 +934,12 @@ class LIBARDOUR_API TriggerBox : public Processor, public std::enable_shared_fro
void send_property_change (PBD::PropertyChange pc);
static PBD::Signal2<void,PBD::PropertyChange,int> TriggerBoxPropertyChange;
std::shared_ptr<MidiBuffer> get_gui_feed_buffer () const;
void dump (std::ostream &) const;
PBD::Signal0<void> Captured;
private:
struct Requests {
std::atomic<bool> stop_all;
@ -966,8 +973,6 @@ class LIBARDOUR_API TriggerBox : public Processor, public std::enable_shared_fro
void maybe_capture (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes);
void finish_recording (BufferSet& bufs);
void set_armed (SlotArmInfo*);
SlotArmInfo* capture_info() const { return _arm_info; }
PBD::Signal0<void> Captured;
/* These four are accessed (read/write) only from process() context */
@ -1025,6 +1030,12 @@ class LIBARDOUR_API TriggerBox : public Processor, public std::enable_shared_fro
PBD::ScopedConnection stop_all_connection;
std::atomic<SlotArmInfo*> _arm_info;
/** A buffer that we use to put newly-arrived MIDI data in for
* the GUI to read (so that it can update itself).
*/
mutable EventRingBuffer<samplepos_t> _gui_feed_fifo;
mutable Glib::Threads::Mutex _gui_feed_reset_mutex;
typedef std::map<std::vector<uint8_t>,std::pair<int,int> > CustomMidiMap;
static CustomMidiMap _custom_midi_map;

View File

@ -22,6 +22,7 @@
#include <cstdlib>
#include <memory>
#include <sstream>
#include <vector>
#include <glibmm.h>
@ -3417,8 +3418,8 @@ Trigger::make_property_quarks ()
SlotArmInfo::SlotArmInfo (Trigger& s)
: slot (s)
, start (0)
, end (0)
, start_samples (0)
, end_samples (0)
, midi_buf (nullptr)
, stretcher (nullptr)
{
@ -3498,6 +3499,7 @@ TriggerBox::TriggerBox (Session& s, DataType dt)
, _record_state (Disabled)
, requests (1024)
, _arm_info (nullptr)
, _gui_feed_fifo (std::min<size_t> (64000, std::max<size_t> (s.sample_rate() / 10, 2 * AudioEngine::instance()->raw_buffer_size (DataType::MIDI))))
{
set_display_to_user (false);
@ -3549,7 +3551,8 @@ TriggerBox::arm_from_another_thread (Trigger& slot, samplepos_t now, uint32_t ch
slot.compute_quantized_transition (now, now_beats, std::numeric_limits<Beats>::max(),
t_bbt, t_beats, t_samples, tmap, slot.quantization());
ai->start = t_samples;
ai->start_samples = t_samples;
ai->start_beats = t_beats;
_arm_info = ai;
}
@ -3583,7 +3586,7 @@ TriggerBox::maybe_capture (BufferSet& bufs, samplepos_t start_sample, samplepos_
bool reached_end = false;
if (!ai->slot.armed()) {
if (!ai->end) {
if (!ai->end_samples) {
/* disarmed: compute end */
Beats start_b;
Beats end_b;
@ -3595,7 +3598,8 @@ TriggerBox::maybe_capture (BufferSet& bufs, samplepos_t start_sample, samplepos_
ai->slot.compute_quantized_transition (start_sample, now_beats, std::numeric_limits<Beats>::max(),
t_bbt, t_beats, t_samples, tmap, ai->slot.quantization());
ai->end = t_samples;
ai->end_samples = t_samples;
ai->end_beats = t_beats;
return;
}
}
@ -3609,25 +3613,25 @@ TriggerBox::maybe_capture (BufferSet& bufs, samplepos_t start_sample, samplepos_
return;
}
if (ai->end.samples() != 0 && (start_sample > ai->end.samples())) {
if (ai->end_samples != 0 && (start_sample > ai->end_samples)) {
return;
}
if (start_sample < ai->start.samples() && end_sample < ai->start.samples() ) {
if (start_sample < ai->start_samples && end_sample < ai->start_samples) {
/* Have not yet reached the start of capture */
return;
}
if (ai->start.samples() >= start_sample && ai->start.samples() < end_sample) {
if (ai->start_samples >= start_sample && ai->start_samples < end_sample) {
/* Let's get going */
offset = ai->start.samples() - start_sample;
offset = ai->start_samples - start_sample;
nframes -= offset;
_record_state = Recording;
}
if ((ai->end.samples() != 0) && (start_sample <= ai->end.samples() && ai->end.samples() < end_sample)) {
if ((ai->end_samples != 0) && (start_sample <= ai->end_samples && ai->end_samples < end_sample)) {
/* we're going to stop */
nframes -= (end_sample - ai->end.samples());
nframes -= (end_sample - ai->end_samples);
reached_end = true;
}
@ -3678,9 +3682,16 @@ TriggerBox::maybe_capture (BufferSet& bufs, samplepos_t start_sample, samplepos_
}
if (!skip_event && (!filter || !filter->filter(ev.buffer(), ev.size()))) {
const samplepos_t event_time (start_sample + ev.time() - ai->start.samples());
if (!ai->end || (event_time < ai->end.samples())) {
ai->midi_buf->write (tmap->quarters_at_sample (event_time), ev.event_type(), ev.size(), ev.buffer());
const samplepos_t event_time (start_sample + ev.time());
if (!ai->end_samples || (event_time < ai->end_samples)) {
/* First write (to an * * RTMidiBufferBeats) uses beat time.
* Second write (to a FIFO) uses sample time.
*
* Both are relative to where we
* started capturing.
*/
ai->midi_buf->write (tmap->quarters_at_sample (event_time) - ai->start_beats, ev.event_type(), ev.size(), ev.buffer());
_gui_feed_fifo.write (event_time - ai->start_samples, Evoral::MIDI_EVENT, ev.size(), ev.buffer());
send_signal = true;
}
}
@ -3688,6 +3699,7 @@ TriggerBox::maybe_capture (BufferSet& bufs, samplepos_t start_sample, samplepos_
}
if (send_signal) {
std::cerr << "SEND CAPTURED\n";
Captured(); /* EMIT SIGNAL */
}
@ -5699,3 +5711,21 @@ TriggerBoxThread::build_midi_source (MIDITrigger* t)
t->set_region_in_worker_thread_from_capture (copy);
}
std::shared_ptr<MidiBuffer>
TriggerBox::get_gui_feed_buffer () const
{
Glib::Threads::Mutex::Lock lm (_gui_feed_reset_mutex);
std::shared_ptr<MidiBuffer> b (new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)));
std::vector<MIDI::byte> buffer (_gui_feed_fifo.capacity());
samplepos_t time;
Evoral::EventType type;
uint32_t size;
while (_gui_feed_fifo.read (&time, &type, &size, &buffer[0])) {
b->push_back (time, type, size, &buffer[0]);
}
return b;
}