Auditioner: collect MIDI Bank/Program changes

This will allow to directly set MIDITrigger PC override
from the auditioner.
This commit is contained in:
Robin Gareus 2022-02-10 01:09:04 +01:00
parent 771db9e238
commit bf273a90ca
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 61 additions and 1 deletions

View File

@ -27,6 +27,8 @@
#include <glibmm/threads.h>
#include "evoral/PatchChange.h"
#include "ardour/ardour.h"
#include "ardour/plugin.h"
#include "ardour/track.h"
@ -59,6 +61,10 @@ public:
void idle_synth_update ();
Evoral::PatchChange<MidiBuffer::TimeType> const& patch_change (uint8_t chn) {
return _patch_change[chn & 0xf];
}
MonitorState monitoring_state () const;
bool needs_monitor() const { return via_monitor; }
@ -81,6 +87,9 @@ public:
void freeze_me (InterThreadInfo&) {}
void unfreeze () {}
/* MIDI Track -- listen to Bank/Patch */
void update_controls (BufferSet const& bufs);
boost::shared_ptr<Region> bounce (InterThreadInfo&, std::string const& name) {
return boost::shared_ptr<Region> ();
}
@ -117,6 +126,8 @@ private:
boost::shared_ptr<Processor> asynth;
Evoral::PatchChange<MidiBuffer::TimeType> _patch_change[16];
PluginInfoPtr lookup_fallback_synth_plugin_info (std::string const&) const;
void drop_ports ();
void lookup_fallback_synth ();

View File

@ -296,6 +296,10 @@ Auditioner::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_s
process_output_buffers (bufs, start_sample, end_sample, nframes, !_session.transport_stopped(), true);
if (_midi_audition) {
update_controls (bufs);
}
/* note: auditioner never writes to disk, so we don't care about the
* disk writer status (it's buffers will always have no data in them).
*/
@ -314,6 +318,46 @@ Auditioner::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_s
return 0;
}
void
Auditioner::update_controls (BufferSet const& bufs)
{
const MidiBuffer& buf = bufs.get_midi(0);
for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
const Evoral::Event<samplepos_t>& ev = *e;
const uint8_t* buf = ev.buffer();
const uint8_t channel = buf[0] & 0x0F;
const int bank = _patch_change[channel].is_set () ? _patch_change[channel].bank () : 0;
switch (midi_parameter_type (buf[0])) {
case MidiPgmChangeAutomation:
if (!_patch_change[channel].is_set ()) {
_patch_change[channel] = Evoral::PatchChange<MidiBuffer::TimeType> (0, channel, 0, 0);
}
_patch_change[channel].set_program (ev.pgm_number ());
break;
case MidiCCAutomation:
switch (ev.cc_number ()) {
case MIDI_CTL_MSB_BANK:
if (!_patch_change[channel].is_set ()) {
_patch_change[channel] = Evoral::PatchChange<MidiBuffer::TimeType> (0, channel, 0, 0);
}
_patch_change[channel].set_bank ((bank & 0x007f) | (ev.cc_value () << 7));
break;
case MIDI_CTL_LSB_BANK:
if (!_patch_change[channel].is_set ()) {
_patch_change[channel] = Evoral::PatchChange<MidiBuffer::TimeType> (0, channel, 0, 0);
}
_patch_change[channel].set_bank ((bank & 0x3f80) | ev.cc_value ());
break;
default:
break;
}
break;
default:
break;
}
}
}
void
Auditioner::audition_region (boost::shared_ptr<Region> region, bool loop)
{
@ -328,6 +372,10 @@ Auditioner::audition_region (boost::shared_ptr<Region> region, bool loop)
Glib::Threads::Mutex::Lock lm (lock);
for (uint8_t c = 0; c < 16; ++c) {
_patch_change[c].unset ();
}
if (boost::dynamic_pointer_cast<AudioRegion>(region) != 0) {
_midi_audition = false;
@ -571,7 +619,8 @@ Auditioner::idle_synth_update ()
pframes_t n_samples = 16;
/* MIDI buffers need to be able to hold patch/pgm change messages. (16 bytes + msg-size) per event */
bufs.ensure_buffers (max (asynth->input_streams (), asynth->output_streams ()), std::max<size_t> (1024, n_samples));
pi->run (bufs, start, start + n_samples, 1.0, n_samples, false);
pi->run (bufs, start, start + n_samples, 1.0, n_samples, false);
update_controls (bufs);
}
void