Vital
Loading...
Searching...
No Matches
voice_handler.h
Go to the documentation of this file.
1#pragma once
2
9#include "circular_queue.h"
10#include "note_handler.h"
11#include "processor_router.h"
12#include "synth_module.h"
13#include "tuning.h"
14
15#include <map>
16#include <list>
17
18namespace vital {
19
44
45 struct AggregateVoice; // Documented below.
46
54 class Voice {
55 public:
57 static constexpr mono_float kDefaultLiftVelocity = 0.5f;
58
72
78
82 Voice() = delete;
83
87 virtual ~Voice() { }
88
90 force_inline AggregateVoice* parent() { return parent_; }
91
93 force_inline const VoiceState& state() { return state_; }
94
96 force_inline const KeyState last_key_state() { return last_key_state_; }
97
99 force_inline const KeyState key_state() { return key_state_; }
100
102 force_inline int event_sample() { return event_sample_; }
103
105 force_inline int voice_index() { return voice_index_; }
106
108 force_inline poly_mask voice_mask() { return voice_mask_; }
109
111 force_inline mono_float aftertouch() { return aftertouch_; }
112
114 force_inline mono_float aftertouch_sample() { return aftertouch_sample_; }
115
117 force_inline mono_float slide() { return slide_; }
118
120 force_inline mono_float slide_sample() { return slide_sample_; }
121
133 force_inline void activate(int midi_note, mono_float tuned_note, mono_float velocity,
134 poly_float last_note, int note_pressed, int note_count,
135 int sample, int channel) {
136 event_sample_ = sample;
137 state_.event = kVoiceOn;
138 state_.midi_note = midi_note;
139 state_.tuned_note = tuned_note;
140 state_.velocity = velocity;
141 state_.lift = kDefaultLiftVelocity;
142 state_.local_pitch_bend = 0.0f;
143 state_.last_note = last_note;
144 state_.note_pressed = note_pressed;
145 state_.note_count = note_count;
146 state_.channel = channel;
147 state_.sostenuto_pressed = false;
148 aftertouch_ = 0.0f;
149 aftertouch_sample_ = 0;
150 slide_ = 0.0f;
151 slide_sample_ = 0;
153 }
154
160 last_key_state_ = key_state_;
161 key_state_ = key_state;
162 }
163
168 last_key_state_ = key_state_;
169 key_state_ = kSustained;
170 }
171
174 return key_state_ == kSustained;
175 }
176
179 return key_state_ == kHeld;
180 }
181
184 return key_state_ == kReleased;
185 }
186
189 return state_.sostenuto_pressed;
190 }
191
196
199 state_.local_pitch_bend = bend;
200 }
201
204 state_.lift = lift;
205 }
206
211 force_inline void deactivate(int sample = 0) {
212 event_sample_ = sample;
213 state_.event = kVoiceOff;
215 }
216
221 force_inline void kill(int sample = 0) {
222 event_sample_ = sample;
223 state_.event = kVoiceKill;
224 }
225
230
233 return event_sample_ >= 0;
234 }
235
242 aftertouch_ = aftertouch;
243 aftertouch_sample_ = sample;
244 }
245
251 force_inline void setSlide(mono_float slide, int sample = 0) {
252 slide_ = slide;
253 slide_sample_ = sample;
254 }
255
258 return aftertouch_sample_ >= 0;
259 }
260
263 return slide_sample_ >= 0;
264 }
265
271 event_sample_ = -1;
272 if (key_state_ == kTriggering)
274 }
275
280 force_inline void shiftVoiceEvent(int num_samples) {
281 event_sample_ -= num_samples;
282 VITAL_ASSERT(event_sample_ >= 0);
283 }
284
288 force_inline void shiftAftertouchEvent(int num_samples) {
289 aftertouch_sample_ -= num_samples;
290 VITAL_ASSERT(aftertouch_sample_ >= 0);
291 }
292
296 force_inline void shiftSlideEvent(int num_samples) {
297 slide_sample_ -= num_samples;
298 VITAL_ASSERT(slide_sample_ >= 0);
299 }
300
303 aftertouch_sample_ = -1;
304 }
305
308 aftertouch_sample_ = -1;
309 }
310
315 event_sample_ = -1;
316 aftertouch_sample_ = -1;
317 }
318
323 force_inline void setSharedVoices(std::vector<Voice*> shared_voices) {
324 for (Voice* voice : shared_voices) {
325 if (voice != this)
326 shared_voices_.push_back(voice);
327 }
328 }
329
336 voice_index_ = voice_index;
337 voice_mask_ = voice_mask;
338 }
339
340 private:
341 int voice_index_;
342 poly_mask voice_mask_;
343 std::vector<Voice*> shared_voices_;
344
345 int event_sample_;
346 VoiceState state_;
347 KeyState last_key_state_;
348 KeyState key_state_;
349
350 int aftertouch_sample_;
351 mono_float aftertouch_;
352
353 int slide_sample_;
354 mono_float slide_;
355
356 AggregateVoice* parent_;
357 };
358
367 std::unique_ptr<Processor> processor;
368 };
369
380 class VoiceHandler : public SynthModule, public NoteHandler {
381 public:
383 static constexpr mono_float kLocalPitchBendRange = 48.0f;
384
389 enum {
394 };
395
405
418
425 VoiceHandler(int num_outputs, int polyphony, bool control_rate = false);
426
428 VoiceHandler() = delete;
429
433 virtual ~VoiceHandler();
434
439 virtual Processor* clone() const override {
440 VITAL_ASSERT(false);
441 return nullptr;
442 }
443
449 virtual void process(int num_samples) override;
450
454 virtual void init() override;
455
460 virtual void setSampleRate(int sample_rate) override;
461
466 void setTuning(const Tuning* tuning) { tuning_ = tuning; }
467
471 int getNumActiveVoices();
472
476 force_inline int getNumPressedNotes() { return pressed_notes_.size(); }
477
483 bool isNotePlaying(int note);
484
491 bool isNotePlaying(int note, int channel);
492
493 // NoteHandler overrides:
494 void allSoundsOff() override;
495 void allNotesOff(int sample) override;
496 void allNotesOff(int sample, int channel) override;
497 void allNotesOffRange(int sample, int from_channel, int to_channel);
498
499 virtual void noteOn(int note, mono_float velocity, int sample, int channel) override;
500 virtual void noteOff(int note, mono_float velocity, int sample, int channel) override;
501
509 void setAftertouch(int note, mono_float aftertouch, int sample, int channel);
510
517 void setChannelAftertouch(int channel, mono_float aftertouch, int sample);
518
522 void setChannelRangeAftertouch(int from_channel, int to_channel, mono_float aftertouch, int sample);
523
527 void setChannelSlide(int channel, mono_float aftertouch, int sample);
528
532 void setChannelRangeSlide(int from_channel, int to_channel, mono_float aftertouch, int sample);
533
535 void sustainOn(int channel);
537 void sustainOff(int sample, int channel);
538
540 void sostenutoOn(int channel);
542 void sostenutoOff(int sample, int channel);
543
545 void sustainOnRange(int from_channel, int to_channel);
547 void sustainOffRange(int sample, int from_channel, int to_channel);
548
550 void sostenutoOnRange(int from_channel, int to_channel);
552 void sostenutoOffRange(int sample, int from_channel, int to_channel);
553
558
566 mod_wheel_values_[channel] = value;
567 }
568
574 for (int i = 0; i < kNumMidiChannels; ++i)
575 mod_wheel_values_[i] = value;
576 }
577
585 pitch_wheel_values_[channel] = value;
586 for (Voice* voice : active_voices_) {
587 if (voice->state().channel == channel && voice->held())
588 voice->setLocalPitchBend(value);
589 }
590 }
591
598 force_inline void setZonedPitchWheel(mono_float value, int from_channel, int to_channel) {
599 VITAL_ASSERT(from_channel < kNumMidiChannels && from_channel >= 0);
600 VITAL_ASSERT(to_channel < kNumMidiChannels && to_channel >= 0);
601 VITAL_ASSERT(to_channel >= from_channel);
602 for (int i = from_channel; i <= to_channel; ++i)
603 zoned_pitch_wheel_values_[i] = value;
604 }
605
607 force_inline Output* voice_event() { return &voice_event_; }
608
610 force_inline Output* retrigger() { return &retrigger_; }
611
613 force_inline Output* reset() { return &reset_; }
614
616 force_inline Output* note() { return &note_; }
617
619 force_inline Output* last_note() { return &last_note_; }
620
622 force_inline Output* note_pressed() { return &note_pressed_; }
623
625 force_inline Output* note_count() { return &note_count_; }
626
628 force_inline Output* note_in_octave() { return &note_in_octave_; }
629
631 force_inline Output* channel() { return &channel_; }
632
634 force_inline Output* velocity() { return &velocity_; }
635
637 force_inline Output* lift() { return &lift_; }
638
640 force_inline Output* aftertouch() { return &aftertouch_; }
641
643 force_inline Output* slide() { return &slide_; }
644
646 force_inline Output* active_mask() { return &active_mask_; }
647
649 force_inline Output* pitch_wheel() { return &pitch_wheel_; }
650
652 force_inline Output* pitch_wheel_percent() { return &pitch_wheel_percent_; }
653
655 force_inline Output* local_pitch_bend() { return &local_pitch_bend_; }
656
658 force_inline Output* mod_wheel() { return &mod_wheel_; }
659
665 force_inline Output* getAccumulatedOutput(Output* output) { return accumulated_outputs_[output].get(); }
666
670 force_inline int polyphony() { return polyphony_; }
671
676
680 virtual ProcessorRouter* getMonoRouter() override { return &global_router_; }
681
685 virtual ProcessorRouter* getPolyRouter() override { return &voice_router_; }
686
687 // Overriding processor management from SynthModule:
688 void addProcessor(Processor* processor) override;
689 void addIdleProcessor(Processor* processor) override;
690 void removeProcessor(Processor* processor) override;
691
695 void addGlobalProcessor(Processor* processor);
696
700 void removeGlobalProcessor(Processor* processor);
701
706 void resetFeedbacks(poly_mask reset_mask) override;
707
714
722
726 Output* registerOutput(Output* output, int index) override;
727
732 void setPolyphony(int polyphony);
733
738 force_inline void setVoiceKiller(const Output* killer) {
739 voice_killer_ = killer;
740 }
741
744 setVoiceKiller(killer->output());
745 }
746
751 force_inline void setVoiceMidi(const Output* midi) {
752 voice_midi_ = midi;
753 }
754
760 legato_ = legato;
761 }
762
765 return legato_;
766 }
767
773 bool isPolyphonic(const Processor* processor) const override;
774
779 virtual void setOversampleAmount(int oversample) override {
781 voice_router_.setOversampleAmount(oversample);
782 global_router_.setOversampleAmount(oversample);
783 }
784
790
796
797 protected:
803 virtual bool shouldAccumulate(Output* output);
804
805 private:
806 // Internal utility methods for grabbing, assigning, and processing voices.
807 Voice* grabVoice();
808 Voice* grabFreeVoice();
809 Voice* grabFreeParallelVoice();
810 Voice* grabVoiceOfType(Voice::KeyState key_state);
811 Voice* getVoiceToKill(int max_voices);
812 int grabNextUnplayedPressedNote();
813 void sortVoicePriority();
814 void addParallelVoices();
815 void prepareVoiceTriggers(AggregateVoice* aggregate_voice, int num_samples);
816 void prepareVoiceValues(AggregateVoice* aggregate_voice);
817 void processVoice(AggregateVoice* aggregate_voice, int num_samples);
818 void clearAccumulatedOutputs();
819 void clearNonaccumulatedOutputs();
820 void accumulateOutputs(int num_samples);
821 void combineAccumulatedOutputs(int num_samples);
822 void writeNonaccumulatedOutputs(poly_mask voice_mask, int num_samples);
823
824 int polyphony_;
825 bool legato_;
826
827 std::map<Output*, std::unique_ptr<Output>> last_voice_outputs_;
828 CircularQueue<std::pair<Output*, Output*>> nonaccumulated_outputs_;
829 std::map<Output*, std::unique_ptr<Output>> accumulated_outputs_;
830
831 const Output* voice_killer_;
832 const Output* voice_midi_;
833
834 int last_num_voices_;
835 poly_float last_played_note_;
836
837 // Outputs published by VoiceHandler for other processors:
838 cr::Output voice_event_;
839 cr::Output retrigger_;
840 cr::Output reset_;
841 cr::Output note_;
842 cr::Output last_note_;
843 cr::Output note_pressed_;
844 cr::Output note_count_;
845 cr::Output note_in_octave_;
846 cr::Output channel_;
847 cr::Output velocity_;
848 cr::Output lift_;
849 cr::Output aftertouch_;
850 cr::Output slide_;
851 cr::Output active_mask_;
852 cr::Output mod_wheel_;
853 cr::Output pitch_wheel_;
854 cr::Output pitch_wheel_percent_;
855 cr::Output local_pitch_bend_;
856
857 bool sustain_[kNumMidiChannels];
858 bool sostenuto_[kNumMidiChannels];
859 mono_float mod_wheel_values_[kNumMidiChannels];
860 mono_float pitch_wheel_values_[kNumMidiChannels];
861 mono_float zoned_pitch_wheel_values_[kNumMidiChannels];
862 mono_float pressure_values_[kNumMidiChannels];
863 mono_float slide_values_[kNumMidiChannels];
864
865 const Tuning* tuning_;
866 VoicePriority voice_priority_;
867 VoiceOverride voice_override_;
868
869 int total_notes_;
870 CircularQueue<int> pressed_notes_;
871
872 // Pools of Voice and AggregateVoice objects:
874 CircularQueue<Voice*> free_voices_;
875 CircularQueue<Voice*> active_voices_;
876
877
879 CircularQueue<AggregateVoice*> active_aggregate_voices_;
880
881 // Two routers: one for each voice (poly), one for global (mono).
882 ProcessorRouter voice_router_;
883 ProcessorRouter global_router_;
884
885 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VoiceHandler)
886 };
887} // namespace vital
888
A class for managing microtonal tunings and custom pitch mappings in Vital.
Definition tuning.h:23
A generic circular buffer (FIFO) data structure that allows adding and removing elements efficiently.
Definition circular_queue.h:32
force_inline int size() const
Returns the current number of elements in the queue.
Definition circular_queue.h:410
An interface for handling MIDI note events within a synthesizer or audio system.
Definition note_handler.h:16
Base class for all signal-processing units in Vital.
Definition processor.h:212
virtual void setOversampleAmount(int oversample)
Sets the oversampling amount and updates the effective sample rate.
Definition processor.h:293
virtual bool isPolyphonic() const
Checks if this Processor is polyphonic by querying its ProcessorRouter.
Definition processor.cpp:73
force_inline Output * output(unsigned int index=0) const
Retrieves the Output pointer at a given index.
Definition processor.h:616
A specialized Processor that manages a directed graph of Processors and ensures correct processing or...
Definition processor_router.h:34
virtual void setOversampleAmount(int oversample) override
Sets the oversampling amount for all Processors in this router.
Definition processor_router.cpp:104
A ProcessorRouter that encapsulates a cohesive unit of functionality in the synthesizer.
Definition synth_module.h:129
A SynthModule and NoteHandler that manages a pool of polyphonic voices, handles note-on/off logic,...
Definition voice_handler.h:380
force_inline Output * velocity()
Returns a pointer to velocity, the note-on velocity.
Definition voice_handler.h:634
force_inline Output * retrigger()
Returns a pointer to the retrigger Output, used for controlling certain envelope triggers.
Definition voice_handler.h:610
void removeGlobalProcessor(Processor *processor)
Removes a Processor from the global router.
Definition voice_handler.cpp:888
void allNotesOffRange(int sample, int from_channel, int to_channel)
Definition voice_handler.cpp:546
force_inline Output * note()
Returns a pointer to the note Output, giving the current tuned note frequency or pitch.
Definition voice_handler.h:616
force_inline void setModWheel(mono_float value, int channel=0)
Sets the mod wheel value for a single channel.
Definition voice_handler.h:564
virtual Processor * clone() const override
Clones this VoiceHandler. Not supported for this class.
Definition voice_handler.h:439
force_inline Output * pitch_wheel()
Returns a pointer to pitch_wheel, storing the pitch-bend range for each channel.
Definition voice_handler.h:649
force_inline int getNumPressedNotes()
Returns how many notes are pressed (including partial states).
Definition voice_handler.h:476
force_inline Output * local_pitch_bend()
Returns a pointer to local_pitch_bend, the per-voice pitch bend output.
Definition voice_handler.h:655
void setPolyphony(int polyphony)
Sets the polyphony to a new value, allocating or freeing voices as needed.
Definition voice_handler.cpp:847
virtual void noteOn(int note, mono_float velocity, int sample, int channel) override
Handles a MIDI note-on event, starting a note with a specified velocity and timing.
Definition voice_handler.cpp:721
void resetFeedbacks(poly_mask reset_mask) override
Resets any feedback paths in the poly router, applying the given mask.
Definition voice_handler.cpp:892
void setChannelAftertouch(int channel, mono_float aftertouch, int sample)
Sets channel-wide aftertouch (applies to all voices on that channel).
Definition voice_handler.cpp:812
force_inline Output * note_pressed()
Returns a pointer to the note_pressed Output, a count of how many times a note was pressed.
Definition voice_handler.h:622
@ kVoicePriority
Priority scheme for stealing or reassigning voices.
Definition voice_handler.h:391
@ kVoiceOverride
Behavior when exceeding polyphony: kill or steal.
Definition voice_handler.h:392
@ kNumInputs
Definition voice_handler.h:393
@ kPolyphony
Desired polyphony setting (1..kMaxActivePolyphony).
Definition voice_handler.h:390
force_inline Output * channel()
Returns a pointer to channel, indicating the MIDI channel of the voice.
Definition voice_handler.h:631
virtual void init() override
Initializes the voice and global routers, then calls SynthModule::init().
Definition voice_handler.cpp:409
void setAftertouch(int note, mono_float aftertouch, int sample, int channel)
Handles per-note aftertouch for a specific note and channel.
Definition voice_handler.cpp:804
force_inline Output * slide()
Returns a pointer to slide, the MPE "slide" expression value.
Definition voice_handler.h:643
void sostenutoOn(int channel)
Turns on sostenuto for a single channel.
Definition voice_handler.cpp:457
int getNumActiveVoices()
Returns the number of currently active voices (not dead).
Definition voice_handler.cpp:425
force_inline int polyphony()
Returns the current maximum polyphony (number of active voices allowed).
Definition voice_handler.h:670
virtual ~VoiceHandler()
Virtual destructor.
Definition voice_handler.cpp:141
bool isNotePlaying(int note)
Checks if a given MIDI note is playing.
Definition voice_handler.cpp:429
void setActiveNonaccumulatedOutput(Output *output)
Marks an Output as "active" for non-accumulated usage (e.g., for the last active voice only).
Definition voice_handler.cpp:941
force_inline Output * voice_event()
Returns a pointer to the voice_event Output, used to track voice On/Off/Kill events.
Definition voice_handler.h:607
virtual ProcessorRouter * getMonoRouter() override
Returns the monophonic (global) ProcessorRouter for this VoiceHandler.
Definition voice_handler.h:680
void removeProcessor(Processor *processor) override
Removes a Processor from this router.
Definition voice_handler.cpp:880
virtual void process(int num_samples) override
Processes audio for a block of samples. For each active voice, triggers events, updates parameters,...
Definition voice_handler.cpp:321
force_inline Output * mod_wheel()
Returns a pointer to mod_wheel, storing the mod wheel value for each channel.
Definition voice_handler.h:658
VoiceOverride
Behavior for assigning a new note when at max polyphony.
Definition voice_handler.h:400
@ kNumVoiceOverrides
Definition voice_handler.h:403
@ kKill
Immediately kill an existing voice to free one.
Definition voice_handler.h:401
@ kSteal
Steal an existing voice that is in a certain state (released/sustained).
Definition voice_handler.h:402
virtual void noteOff(int note, mono_float velocity, int sample, int channel) override
Handles a MIDI note-off event, releasing a currently active note.
Definition voice_handler.cpp:752
void sostenutoOffRange(int sample, int from_channel, int to_channel)
Turns off sostenuto for a range of channels, prompting release if not sustained.
Definition voice_handler.cpp:503
force_inline void setPitchWheel(mono_float value, int channel=0)
Sets the pitch wheel value for a single channel, applying to all held voices on that channel.
Definition voice_handler.h:583
void addGlobalProcessor(Processor *processor)
Adds a Processor to the "global" (monophonic) router, e.g. for final mixing or master effects.
Definition voice_handler.cpp:884
force_inline Output * note_count()
Returns a pointer to note_count, a global note counter.
Definition voice_handler.h:625
force_inline Output * aftertouch()
Returns a pointer to aftertouch, storing per-voice or channel-based aftertouch.
Definition voice_handler.h:640
virtual void setOversampleAmount(int oversample) override
Sets the oversampling factor for both SynthModule and the internal poly/mono routers.
Definition voice_handler.h:779
force_inline bool legato()
Returns true if legato mode is enabled.
Definition voice_handler.h:764
force_inline Output * getAccumulatedOutput(Output *output)
Retrieves the accumulated Output associated with a given output pointer.
Definition voice_handler.h:665
force_inline Output * pitch_wheel_percent()
Returns a pointer to pitch_wheel_percent, a normalized [0..1] version of pitch_wheel.
Definition voice_handler.h:652
force_inline Output * reset()
Returns a pointer to the reset Output, indicating a full voice reset (On from Dead).
Definition voice_handler.h:613
void allNotesOff(int sample) override
Turns off all currently active notes, optionally specifying a sample index for timing.
Definition voice_handler.cpp:530
VoicePriority
Determines the voice stealing strategy (oldest, newest, highest, etc.).
Definition voice_handler.h:410
@ kRoundRobin
Definition voice_handler.h:415
@ kHighest
Definition voice_handler.h:413
@ kOldest
Definition voice_handler.h:412
@ kNumVoicePriorities
Definition voice_handler.h:416
@ kNewest
Definition voice_handler.h:411
@ kLowest
Definition voice_handler.h:414
force_inline void setModWheelAllChannels(mono_float value)
Sets the mod wheel value for all channels at once.
Definition voice_handler.h:573
void sustainOff(int sample, int channel)
Turns off sustain for a single channel, prompting voices to release.
Definition voice_handler.cpp:449
void addProcessor(Processor *processor) override
Adds a Processor to be managed by this router.
Definition voice_handler.cpp:870
static constexpr mono_float kLocalPitchBendRange
Range of local pitch bend in semitones for each voice.
Definition voice_handler.h:383
force_inline void setVoiceKiller(const Output *killer)
Specifies an Output from a Processor used to detect silence or inactivity for voice killing.
Definition voice_handler.h:738
virtual ProcessorRouter * getPolyRouter() override
Returns the polyphonic (voice) ProcessorRouter for this VoiceHandler.
Definition voice_handler.h:685
void addIdleProcessor(Processor *processor) override
Adds a Processor that should remain idle (not processed) in the router.
Definition voice_handler.cpp:875
force_inline void setZonedPitchWheel(mono_float value, int from_channel, int to_channel)
Sets pitch wheel in a zoned manner for a range of MIDI channels.
Definition voice_handler.h:598
void setTuning(const Tuning *tuning)
Sets the custom Tuning object (if any) for note->frequency conversion.
Definition voice_handler.h:466
VoiceHandler()=delete
Disabled default constructor; must specify polyphony and output count.
void allSoundsOff() override
Immediately turns off all sounding notes and stops all sound production.
Definition voice_handler.cpp:517
void setInactiveNonaccumulatedOutput(Output *output)
Marks an Output as "inactive" for non-accumulated usage, effectively disabling it.
Definition voice_handler.cpp:949
mono_float getLastActiveNote() const
Gets the last active note's tuned frequency (or 0 if none).
Definition voice_handler.cpp:863
void sostenutoOff(int sample, int channel)
Turns off sostenuto for a single channel, prompting release if not sustained.
Definition voice_handler.cpp:465
void sustainOffRange(int sample, int from_channel, int to_channel)
Turns off sustain for a range of channels, prompting voices to release.
Definition voice_handler.cpp:482
Output * registerOutput(Output *output) override
Registers an Output with this VoiceHandler, returning a pointer to a new accumulated or single-lane O...
Definition voice_handler.cpp:896
virtual void setSampleRate(int sample_rate) override
Sets the sample rate for both mono/global and voice (poly) routers.
Definition voice_handler.cpp:416
force_inline Output * lift()
Returns a pointer to lift, the note-off velocity or release velocity.
Definition voice_handler.h:637
force_inline void setVoiceKiller(const Processor *killer)
Overload for setting the voice killer from a Processor directly.
Definition voice_handler.h:743
force_inline Output * last_note()
Returns a pointer to the last_note Output, giving the previous note (for legato transitions).
Definition voice_handler.h:619
force_inline Output * active_mask()
Returns a pointer to active_mask, a mask that indicates which voices are active.
Definition voice_handler.h:646
Output * registerControlRateOutput(Output *output, bool active)
Registers a control-rate Output with the VoiceHandler.
Definition voice_handler.cpp:914
virtual bool shouldAccumulate(Output *output)
Determines whether an Output should be summed across voices (accumulated) or handled individually.
Definition voice_handler.cpp:316
void sustainOnRange(int from_channel, int to_channel)
Turns on sustain for a range of channels.
Definition voice_handler.cpp:477
void sustainOn(int channel)
Turns on sustain for a single channel.
Definition voice_handler.cpp:445
force_inline void setLegato(bool legato)
Enables or disables legato mode (disables retriggers if still in Held state).
Definition voice_handler.h:759
force_inline void setVoiceMidi(const Output *midi)
Sets the Output that provides the current MIDI note for the voice.
Definition voice_handler.h:751
force_inline Output * note_in_octave()
Returns a pointer to note_in_octave, a fractional note position in [0..1).
Definition voice_handler.h:628
void setChannelRangeAftertouch(int from_channel, int to_channel, mono_float aftertouch, int sample)
Sets channel-wide aftertouch for a range of channels.
Definition voice_handler.cpp:821
poly_mask getCurrentVoiceMask()
Returns a mask for the last active voice, used for writing to output buffers.
Definition voice_handler.cpp:556
void setChannelSlide(int channel, mono_float aftertouch, int sample)
Sets channel-wide MPE "slide" for a single channel.
Definition voice_handler.cpp:830
void setChannelRangeSlide(int from_channel, int to_channel, mono_float aftertouch, int sample)
Sets channel-wide MPE "slide" for a range of channels.
Definition voice_handler.cpp:838
void sostenutoOnRange(int from_channel, int to_channel)
Turns on sostenuto for a range of channels.
Definition voice_handler.cpp:493
Represents a single playing note/voice, including voice-state and event handling.
Definition voice_handler.h:54
force_inline bool sustained()
Returns true if the voice is in the kSustained state.
Definition voice_handler.h:173
force_inline bool released()
Returns true if the voice is in the kReleased state.
Definition voice_handler.h:183
force_inline void shiftAftertouchEvent(int num_samples)
Shifts the aftertouch event sample index by num_samples.
Definition voice_handler.h:288
force_inline bool held()
Returns true if the voice is in the kHeld state.
Definition voice_handler.h:178
force_inline void setSostenuto(bool sostenuto)
Sets the sostenuto flag on or off.
Definition voice_handler.h:193
static constexpr mono_float kDefaultLiftVelocity
Default lift velocity to use if none is provided.
Definition voice_handler.h:57
force_inline void clearSlideEvent()
Clears the unprocessed slide event, if any.
Definition voice_handler.h:307
force_inline void setVoiceInfo(int voice_index, poly_mask voice_mask)
Sets the voice index within its parallel group and the corresponding SIMD mask.
Definition voice_handler.h:335
force_inline bool sostenuto()
Returns true if the voice has sostenuto pressed.
Definition voice_handler.h:188
virtual ~Voice()
Virtual destructor.
Definition voice_handler.h:87
force_inline mono_float slide()
Returns the current slide (MPE expression) value for this voice.
Definition voice_handler.h:117
force_inline void kill(int sample=0)
Immediately kills this voice (disregarding release).
Definition voice_handler.h:221
KeyState
Describes the lifecycle stage of a voice: kTriggering -> kHeld -> kReleased -> kDead,...
Definition voice_handler.h:64
@ kDead
The voice is no longer active.
Definition voice_handler.h:69
@ kReleased
The note has ended (off event) and is releasing.
Definition voice_handler.h:68
@ kSustained
The note has ended, but sustain pedal is holding it on.
Definition voice_handler.h:67
@ kNumStates
Definition voice_handler.h:70
@ kTriggering
Note-on occurred, but hasn't processed yet.
Definition voice_handler.h:65
@ kHeld
The note is actively held down.
Definition voice_handler.h:66
force_inline void sustain()
Switches this voice to the kSustained state, typically when a sustain pedal is active.
Definition voice_handler.h:167
force_inline mono_float aftertouch()
Returns the current aftertouch value for this voice.
Definition voice_handler.h:111
force_inline void setLocalPitchBend(mono_float bend)
Sets the local pitch bend (used for legato transitions or channel pitch bend).
Definition voice_handler.h:198
force_inline void clearEvents()
Clears both note-on/off events and aftertouch events, marking them processed.
Definition voice_handler.h:314
force_inline int event_sample()
Returns the sample index at which the latest event (on/off) was triggered.
Definition voice_handler.h:102
force_inline poly_mask voice_mask()
Returns the SIMD mask representing this voice's active lanes.
Definition voice_handler.h:108
force_inline mono_float aftertouch_sample()
Returns the sample index at which the latest aftertouch event occurred.
Definition voice_handler.h:114
force_inline void setSharedVoices(std::vector< Voice * > shared_voices)
Stores references to other Voices in the same parallel group for advanced sharing logic.
Definition voice_handler.h:323
force_inline void setAftertouch(mono_float aftertouch, int sample=0)
Sets the aftertouch (pressure) value for the voice.
Definition voice_handler.h:241
force_inline const KeyState last_key_state()
Returns the previous key state (before the most recent update).
Definition voice_handler.h:96
force_inline void markDead()
Marks this voice as kDead, meaning it's completely inactive.
Definition voice_handler.h:227
force_inline int voice_index()
Returns the index of this voice within an AggregateVoice (also the SIMD lane grouping).
Definition voice_handler.h:105
force_inline void deactivate(int sample=0)
Deactivates (turns off) this voice with a note-off event, transitioning to kReleased.
Definition voice_handler.h:211
Voice()=delete
Disabled default constructor: Voice must belong to an AggregateVoice.
force_inline void shiftVoiceEvent(int num_samples)
Shifts the event sample index by num_samples (e.g., for partial block processing).
Definition voice_handler.h:280
force_inline void setKeyState(KeyState key_state)
Sets the key state of this voice (e.g., from Triggering to Held).
Definition voice_handler.h:159
force_inline const VoiceState & state()
Returns a const reference to the VoiceState struct that holds all relevant data.
Definition voice_handler.h:93
force_inline bool hasNewEvent()
Checks if there is a new (non-processed) on/off event for this voice.
Definition voice_handler.h:232
force_inline AggregateVoice * parent()
Returns the pointer to the parent AggregateVoice.
Definition voice_handler.h:90
force_inline const KeyState key_state()
Returns the current key state.
Definition voice_handler.h:99
force_inline void shiftSlideEvent(int num_samples)
Shifts the slide event sample index by num_samples.
Definition voice_handler.h:296
force_inline bool hasNewSlide()
Returns true if there's a new slide event not yet processed.
Definition voice_handler.h:262
force_inline void setSlide(mono_float slide, int sample=0)
Sets the MPE "slide" value for the voice (often CC#74).
Definition voice_handler.h:251
force_inline void completeVoiceEvent()
Completes (consumes) the voice event, marking it as processed. If the voice was kTriggering,...
Definition voice_handler.h:270
force_inline void clearAftertouchEvent()
Clears the unprocessed aftertouch event, if any.
Definition voice_handler.h:302
force_inline bool hasNewAftertouch()
Returns true if there's a new aftertouch event not yet processed.
Definition voice_handler.h:257
force_inline void setLiftVelocity(mono_float lift)
Adjusts the lift velocity (release velocity) of the note-off.
Definition voice_handler.h:203
force_inline void activate(int midi_note, mono_float tuned_note, mono_float velocity, poly_float last_note, int note_pressed, int note_count, int sample, int channel)
Activates (starts) the voice with the given note parameters.
Definition voice_handler.h:133
force_inline mono_float slide_sample()
Returns the sample index at which the latest slide event occurred.
Definition voice_handler.h:120
#define VITAL_ASSERT(x)
Definition common.h:11
#define force_inline
Definition common.h:23
Contains classes and functions used within the Vital synthesizer framework.
VoiceEvent
Enumerates different states or events of a synth voice's lifecycle.
Definition common.h:74
@ kInvalid
Definition common.h:75
@ kVoiceOn
Definition common.h:77
@ kVoiceKill
Definition common.h:81
@ kVoiceOff
Definition common.h:80
constexpr int kNumMidiChannels
MIDI channels available per device.
Definition common.h:57
float mono_float
Definition common.h:33
Declares the ProcessorRouter class, which manages a graph of Processors and their dependencies.
An aggregate grouping that pairs multiple (parallel) voices with a shared Processor instance.
Definition voice_handler.h:365
CircularQueue< Voice * > voices
Collection of active Voice pointers.
Definition voice_handler.h:366
std::unique_ptr< Processor > processor
A single processor instance shared by these voices.
Definition voice_handler.h:367
Holds and manages a buffer of samples (poly_float) for a Processor's output.
Definition processor.h:35
Holds state data for a single voice, such as MIDI note, velocity, pitch bend, etc.
Definition voice_handler.h:24
int channel
Which MIDI channel this voice is associated with.
Definition voice_handler.h:41
int note_count
A global note counter (incremented with each note-on).
Definition voice_handler.h:40
VoiceState()
Default constructor initializes state to neutral or inactive values.
Definition voice_handler.h:28
int midi_note
MIDI note (0-127 usually).
Definition voice_handler.h:33
VoiceEvent event
The most recent voice event (on/off/kill).
Definition voice_handler.h:32
int note_pressed
Pressed note count (e.g., for note priority logic).
Definition voice_handler.h:39
mono_float local_pitch_bend
Per-voice pitch bend amount for legato-like transitions.
Definition voice_handler.h:38
mono_float velocity
Velocity of the note-on event.
Definition voice_handler.h:36
mono_float lift
Velocity of the note-off (a.k.a. release velocity).
Definition voice_handler.h:37
mono_float tuned_note
Possibly adjusted by a Tuning object.
Definition voice_handler.h:34
bool sostenuto_pressed
True if this voice is currently held by sostenuto pedal.
Definition voice_handler.h:42
poly_float last_note
Holds the last note played for this voice.
Definition voice_handler.h:35
A specialized Output that always runs at control rate (buffer_size = 1).
Definition processor.h:189
Represents a vector of floating-point values using SIMD instructions.
Definition poly_values.h:600
Represents a vector of integer values using SIMD instructions.
Definition poly_values.h:56
Defines the SynthModule class which extends ProcessorRouter to form a building block of the Vital syn...