Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
midi_parameter_map.hpp File Reference

Map incoming MIDI Control Change messages to plugin parameters, with a "learn" mode — the equivalent of a host's MIDI-mapping panel, owned by the plugin so it works in every host. More...

#include <algorithm>
#include <array>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <pulp/runtime/spsc_queue.hpp>
#include <pulp/state/store.hpp>

Go to the source code of this file.

Classes

struct  pulp::state::MidiMapScale
 Normalized [0, 1] output window a CC sweep is mapped onto. More...
class  pulp::state::MidiParameterMap

Namespaces

namespace  pulp
namespace  pulp::state
 SequencerStateChannel is the audio-safe transport for a plugin's structured NON-parameter state: the bulk, observable state a step sequencer / mod-matrix / pattern engine holds outside its automatable parameter set (e.g.

Detailed Description

Map incoming MIDI Control Change messages to plugin parameters, with a "learn" mode — the equivalent of a host's MIDI-mapping panel, owned by the plugin so it works in every host.

Thread model: mappings are added / armed from the UI thread and applied from the audio thread. UI calls go through a lock-free command queue; the audio thread drains it once per block via pump() and then routes each incoming CC through handle_cc(), which writes the parameter with set_normalized_rt. The value change is picked up by the format adapter's post-process diff and pushed to the host, so a CC-driven move is recorded as parameter automation.

Value scaling: a controller need not drive its parameter across the whole range. Each mapping carries a MidiMapScale — the normalized [0, 1] window the CC sweep is mapped onto. CC 0..127 spans min..max; the endpoints are clamped into [0, 1], and min > max inverts the response (a knob turned up lowers the parameter). The default window is the full range, so a mapping created without a scale behaves exactly as an unscaled 0..127 → 0..1 sweep. Shaping (log/skew) is a property of the target parameter's own ParamRange, not of the map — the map only supplies the normalized window.

Usage (in the processor): midi_map_.pump(); // top of process() for (auto& e : midi_in) if (e.is_cc()) midi_map_.handle_cc(state(), e.channel(), e.cc_number(), e.cc_value()); And from the UI: midi_map_.arm_learn(kCutoff); // next CC binds to kCutoff midi_map_.set_mapping(0, 74, kCutoff); // or map explicitly midi_map_.set_mapping(0, 1, kMix, {0.25f, 0.75f}); // sweep only the middle midi_map_.set_mapping(0, 7, kGain, {1.0f, 0.0f}); // inverted