29 static_assert(MaximumVoices > 0);
30 static constexpr std::size_t
capacity() noexcept {
39 if (voice_index >= MaximumVoices || note_id == 0 ||
40 (!event.is_note_on() && !event.is_note_off()))
42 auto& voice = voices_[voice_index];
43 const bool is_attack =
event.is_note_on() &&
event.velocity() != 0;
48 if (note_id <= voice.note_id)
50 voice = {
true,
event.channel(),
event.note(),
event.velocity(), note_id, 0.0f, 0.0f,
54 if (!voice.active || voice.channel != event.channel() || voice.note != event.note() ||
55 voice.note_id != note_id)
57 const auto watermark = voice.note_id;
59 voice.note_id = watermark;
64 if (voice_index >= MaximumVoices || !expression.active || expression.note_id == 0)
66 if (!std::isfinite(expression.pitch_bend_semitones) ||
67 !std::isfinite(expression.pressure) || !std::isfinite(expression.timbre))
69 auto& voice = voices_[voice_index];
70 if (!voice.active || voice.channel != expression.channel || voice.note != expression.note ||
71 voice.note_id != expression.note_id)
73 const double pitch_cents =
static_cast<double>(expression.pitch_bend_semitones) * 100.0;
74 if (!std::isfinite(pitch_cents) ||
75 std::abs(pitch_cents) >
static_cast<double>(std::numeric_limits<float>::max()))
77 voice.pitch_cents =
static_cast<float>(pitch_cents);
78 voice.pressure = std::clamp(expression.pressure, 0.0f, 1.0f);
79 voice.timbre = std::clamp(expression.timbre, 0.0f, 1.0f);
84 std::uint32_t frame_count)
const noexcept {
85 if (voice_index >= MaximumVoices)
87 if (!destination.prepared())
89 if (frame_count > destination.max_frames())
91 if (destination.max_lanes() < 4)
93 const auto& voice = voices_[voice_index];
94 if (!std::isfinite(voice.pitch_cents) || !std::isfinite(voice.pressure) ||
95 !std::isfinite(voice.timbre))
97 auto result = destination.begin_block(frame_count);
100 if (!(result = destination.add_constant(
102 voice.active ?
static_cast<float>(voice.velocity) / 127.0f : 0.0f))
116 return voice_index < MaximumVoices ? &voices_[voice_index] :
nullptr;
120 if (voice_index >= MaximumVoices || note_id == 0 || !voices_[voice_index].active ||
121 voices_[voice_index].note_id != note_id)
123 const auto watermark = voices_[voice_index].note_id;
124 voices_[voice_index] = {};
125 voices_[voice_index].note_id = watermark;
140 std::array<MidiVoiceModulationState, MaximumVoices> voices_{};
Definition midi_voice_modulation_adapter.hpp:27
VoiceModulationResult write_voice(std::size_t voice_index, VoiceModulationBuffer &destination, std::uint32_t frame_count) const noexcept
Definition midi_voice_modulation_adapter.hpp:83
static constexpr std::size_t maximum_event_amplification() noexcept
Definition midi_voice_modulation_adapter.hpp:33
static constexpr std::size_t capacity() noexcept
Definition midi_voice_modulation_adapter.hpp:30
void hot_swap_reset() noexcept
Definition midi_voice_modulation_adapter.hpp:135
bool note_event(std::size_t voice_index, const midi::MidiEvent &event, midi::MpeNoteGeneration note_id) noexcept
Definition midi_voice_modulation_adapter.hpp:37
bool release_voice(std::size_t voice_index, midi::MpeNoteGeneration note_id) noexcept
Definition midi_voice_modulation_adapter.hpp:119
void reset() noexcept
Definition midi_voice_modulation_adapter.hpp:132
const MidiVoiceModulationState * state(std::size_t voice_index) const noexcept
Definition midi_voice_modulation_adapter.hpp:115
void flush() noexcept
Definition midi_voice_modulation_adapter.hpp:129
bool mpe_expression(std::size_t voice_index, const midi::MpeNoteState &expression) noexcept
Definition midi_voice_modulation_adapter.hpp:63
Definition voice_modulation_buffer.hpp:78
MPE (MIDI Polyphonic Expression) voice tracker.
Definition analyzer_provider.hpp:12
@ PitchCents
Definition voice_modulation_buffer.hpp:11
@ Gain
Definition voice_modulation_buffer.hpp:10
@ Pressure
Definition voice_modulation_buffer.hpp:13
@ Timbre
Definition voice_modulation_buffer.hpp:14
@ NonFiniteValue
Definition voice_modulation_buffer.hpp:35
@ NotPrepared
Definition voice_modulation_buffer.hpp:32
@ InvalidTarget
Definition voice_modulation_buffer.hpp:34
@ LaneOverflow
Definition voice_modulation_buffer.hpp:37
@ InvalidFrameCount
Definition voice_modulation_buffer.hpp:33
std::uint64_t MpeNoteGeneration
Stable identity assigned to one accepted MPE note-on generation.
Definition mpe_voice_tracker.hpp:36
Definition midi_voice_modulation_adapter.hpp:16
float pressure
Definition midi_voice_modulation_adapter.hpp:23
bool active
Definition midi_voice_modulation_adapter.hpp:17
std::uint8_t note
Definition midi_voice_modulation_adapter.hpp:19
float pitch_cents
Definition midi_voice_modulation_adapter.hpp:22
float timbre
Definition midi_voice_modulation_adapter.hpp:24
std::uint8_t channel
Definition midi_voice_modulation_adapter.hpp:18
std::uint8_t velocity
Definition midi_voice_modulation_adapter.hpp:20
midi::MpeNoteGeneration note_id
Definition midi_voice_modulation_adapter.hpp:21
Definition voice_modulation_buffer.hpp:40
Timestamped MIDI event combining a choc::midi::ShortMessage with timing info.
Definition message.hpp:32
Per-note state maintained by MpeVoiceTracker.
Definition mpe_voice_tracker.hpp:44