Vital
Loading...
Searching...
No Matches
processor.h
Go to the documentation of this file.
1
15#pragma once
16
17#include "common.h"
18#include "poly_utils.h"
19
20#include <cstring>
21#include <vector>
22
23namespace vital {
24
25 class Processor;
26 class ProcessorRouter;
27
35 struct Output {
41 Output(int size = kMaxBufferSize, int max_oversample = 1) {
42 VITAL_ASSERT(size > 0);
43
44 owner = nullptr;
45 buffer_size = size * max_oversample;
46 owned_buffer = std::make_unique<poly_float[]>(buffer_size);
47 buffer = owned_buffer.get();
50 }
51
55 virtual ~Output() { }
56
63 force_inline void trigger(poly_mask mask, poly_float value, poly_int offset) {
64 trigger_mask |= mask;
67 }
68
73 trigger_mask = 0;
74 trigger_value = 0.0f;
76 }
77
84
90 return buffer_size == 1;
91 }
92
98 void ensureBufferSize(int new_max_buffer_size) {
99 if (buffer_size >= new_max_buffer_size || buffer_size == 1)
100 return;
101
102 buffer_size = new_max_buffer_size;
103 bool buffer_is_original = (buffer == owned_buffer.get());
104 owned_buffer = std::make_unique<poly_float[]>(buffer_size);
105 if (buffer_is_original)
106 buffer = owned_buffer.get();
107 clearBuffer();
108 }
109
111 std::unique_ptr<poly_float[]> owned_buffer;
113
118
119 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Output)
120 };
121
128 struct Input {
132 Input() : source(nullptr) { }
133
134 const Output* source;
135
142 return source->buffer[i];
143 }
144
150 force_inline const poly_float& operator[](std::size_t i) {
151 return source->buffer[i];
152 }
153
154 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Input)
155 };
156
181
182 namespace cr {
189 struct Output : public ::vital::Output {
194 owner = nullptr;
195 buffer_size = 1;
196 owned_buffer = std::make_unique<poly_float[]>(1);
198 clearBuffer();
199 clearTrigger();
200 }
201 };
202 } // namespace cr
203
212 class Processor {
213 public:
221 Processor(int num_inputs, int num_outputs, bool control_rate = false, int max_oversample = 1);
222
226 virtual ~Processor() { }
227
232 virtual Processor* clone() const = 0;
233
238 virtual bool hasState() const { return true; }
239
244 virtual void process(int num_samples) = 0;
245
252 virtual void processWithInput(const poly_float* audio_in, int num_samples) { VITAL_ASSERT(false); }
253
258 virtual void init() {
260 state_->initialized = true;
261 }
262
267 virtual void reset(poly_mask reset_mask) { }
268
272 virtual void hardReset() { reset(poly_mask(-1)); }
273
277 bool initialized() {
278 return state_->initialized;
279 }
280
285 virtual void setSampleRate(int sample_rate) {
286 state_->sample_rate = sample_rate * state_->oversample_amount;
287 }
288
293 virtual void setOversampleAmount(int oversample) {
294 // Remove old oversampling factor, set new, then re-add.
295 state_->sample_rate /= state_->oversample_amount;
296 state_->oversample_amount = oversample;
297 state_->sample_rate *= state_->oversample_amount;
298
299 // Ensure our outputs match the new oversample buffer size.
300 for (int i = 0; i < numOwnedOutputs(); ++i)
302 for (int i = 0; i < numOutputs(); ++i)
303 output(i)->ensureBufferSize(kMaxBufferSize * oversample);
304 }
305
310 force_inline bool enabled() const {
311 return state_->enabled;
312 }
313
318 virtual void enable(bool enable) {
319 state_->enabled = enable;
320 }
321
327 return state_->sample_rate;
328 }
329
335 return state_->oversample_amount;
336 }
337
343 return state_->control_rate;
344 }
345
350 virtual void setControlRate(bool control_rate) {
351 state_->control_rate = control_rate;
352 }
353
360 force_inline poly_mask getResetMask(int input_index) const {
361 poly_float trigger_val = inputs_->at(input_index)->source->trigger_value;
362 return poly_float::equal(trigger_val, kVoiceOn);
363 }
364
373 force_inline void clearOutputBufferForReset(poly_mask reset_mask, int input_index, int output_index) const {
374 poly_float* audio_out = output(output_index)->buffer;
375 poly_int trigger_offset = input(input_index)->source->trigger_offset & reset_mask;
376
377 // Example logic for partial clearing (based on trigger offsets).
378 int num_samples_first = trigger_offset[0];
379 poly_int mask(0, 0, -1, -1);
380 for (int i = 0; i < num_samples_first; ++i)
381 audio_out[i] = audio_out[i] & mask;
382
383 mask = poly_int(-1, -1, 0, 0);
384 int num_samples_second = trigger_offset[2];
385 for (int i = 0; i < num_samples_second; ++i)
386 audio_out[i] = audio_out[i] & mask;
387 }
388
394 bool inputMatchesBufferSize(int input = 0);
395
401 bool checkInputAndOutputSize(int num_samples);
402
407 virtual bool isPolyphonic() const;
408
413 void plug(const Output* source);
414
420 void plug(const Output* source, unsigned int input_index);
421
426 void plug(const Processor* source);
427
433 void plug(const Processor* source, unsigned int input_index);
434
439 void plugNext(const Output* source);
440
445 void plugNext(const Processor* source);
446
451 void useInput(Input* input);
452
458 void useInput(Input* input, int index);
459
464 void useOutput(Output* output);
465
471 void useOutput(Output* output, int index);
472
477 int connectedInputs();
478
483 virtual void unplugIndex(unsigned int input_index);
484
489 virtual void unplug(const Output* source);
490
495 virtual void unplug(const Processor* source);
496
501 virtual void numInputsChanged() { }
502
511
517 return router_;
518 }
519
525
531 virtual void registerInput(Input* input, int index);
532
539 virtual Output* registerOutput(Output* output, int index);
540
545 virtual void registerInput(Input* input);
546
553
558 return static_cast<int>(inputs_->size());
559 }
560
565 return static_cast<int>(outputs_->size());
566 }
567
572 return static_cast<int>(owned_inputs_.size());
573 }
574
579 return static_cast<int>(owned_outputs_.size());
580 }
581
587 force_inline Input* input(unsigned int index = 0) const {
588 VITAL_ASSERT(index < inputs_->size());
589 return (*inputs_)[index];
590 }
591
598 return input(index)->source->owner && input(index)->source->owner->isPolyphonic();
599 }
600
606 force_inline Input* ownedInput(unsigned int index = 0) const {
607 VITAL_ASSERT(index < owned_inputs_.size());
608 return owned_inputs_[index].get();
609 }
610
616 force_inline Output* output(unsigned int index = 0) const {
617 VITAL_ASSERT(index < outputs_->size());
618 return (*outputs_)[index];
619 }
620
626 force_inline Output* ownedOutput(unsigned int index = 0) const {
627 VITAL_ASSERT(index < owned_outputs_.size());
628 return owned_outputs_[index].get();
629 }
630
635 void setPluggingStart(int start) {
636 plugging_start_ = start;
637 }
638
639 protected:
645 Output* addOutput(int oversample = 1);
646
651 Input* addInput();
652
653 std::shared_ptr<ProcessorState> state_;
654
656
657 std::vector<std::shared_ptr<Input>> owned_inputs_;
658 std::vector<std::shared_ptr<Output>> owned_outputs_;
659
660 std::shared_ptr<std::vector<Input*>> inputs_;
661 std::shared_ptr<std::vector<Output*>> outputs_;
662
664
665 static const Output null_source_;
666
667 JUCE_LEAK_DETECTOR(Processor)
668 };
669} // namespace vital
Base class for all signal-processing units in Vital.
Definition processor.h:212
force_inline ProcessorRouter * router() const
Returns the ProcessorRouter that currently owns this Processor.
Definition processor.h:516
std::shared_ptr< ProcessorState > state_
Shared state (sample rate, oversample, etc.)
Definition processor.h:653
virtual void unplugIndex(unsigned int input_index)
Removes the connection at a specified input index, if any.
Definition processor.cpp:161
bool initialized()
Returns whether this Processor has been initialized.
Definition processor.h:277
Processor(int num_inputs, int num_outputs, bool control_rate=false, int max_oversample=1)
Constructs a Processor with a given number of inputs/outputs and oversampling.
Definition processor.cpp:25
force_inline int numOutputs() const
Returns the total number of Output pointers (owned or otherwise).
Definition processor.h:564
force_inline int numInputs() const
Returns the total number of Input pointers (owned or otherwise).
Definition processor.h:557
virtual void setControlRate(bool control_rate)
Sets whether this Processor runs at control rate.
Definition processor.h:350
virtual void numInputsChanged()
Called when the number of inputs changes (e.g., new connections). Subclasses may override for dynamic...
Definition processor.h:501
virtual void setOversampleAmount(int oversample)
Sets the oversampling amount and updates the effective sample rate.
Definition processor.h:293
virtual Output * registerOutput(Output *output, int index)
Registers a new Output in the output list at a specified index.
Definition processor.cpp:223
void plugNext(const Output *source)
Connects an external Output to the first available (unplugged) input.
Definition processor.cpp:104
Input * addInput()
Creates and registers a new Input, initially connected to null_source_.
Definition processor.cpp:246
int plugging_start_
The index at which plugNext starts searching for an unplugged input.
Definition processor.h:655
virtual ~Processor()
Virtual destructor.
Definition processor.h:226
void useOutput(Output *output)
Uses an existing Output object as this Processor's first output.
Definition processor.cpp:138
virtual bool hasState() const
Indicates whether this Processor requires per-voice state.
Definition processor.h:238
virtual bool isPolyphonic() const
Checks if this Processor is polyphonic by querying its ProcessorRouter.
Definition processor.cpp:73
force_inline Input * input(unsigned int index=0) const
Retrieves the Input pointer at a given index.
Definition processor.h:587
force_inline int getSampleRate() const
Retrieves the current (effective) sample rate.
Definition processor.h:326
force_inline bool enabled() const
Checks if this Processor is enabled.
Definition processor.h:310
void useInput(Input *input)
Uses an existing Input object as this Processor's first input.
Definition processor.cpp:126
virtual void registerInput(Input *input, int index)
Registers a new input, appending it to the input list.
Definition processor.cpp:213
force_inline bool isControlRate() const
Checks if this Processor is running at control rate (buffer_size == 1).
Definition processor.h:342
bool inputMatchesBufferSize(int input=0)
Checks whether the buffer size of a particular input matches the size needed by this Processor.
Definition processor.cpp:42
force_inline poly_mask getResetMask(int input_index) const
Retrieves a mask indicating which voices triggered a note-on event. Compares the input's trigger_valu...
Definition processor.h:360
static const Output null_source_
A null (dummy) source used for unconnected inputs.
Definition processor.h:665
ProcessorRouter * getTopLevelRouter() const
Gets the topmost (root) ProcessorRouter by traversing parent routers.
Definition processor.cpp:190
std::shared_ptr< std::vector< Input * > > inputs_
All inputs, owned or external.
Definition processor.h:660
bool checkInputAndOutputSize(int num_samples)
Checks if all inputs and outputs have buffers big enough for num_samples.
Definition processor.cpp:52
virtual void hardReset()
Called to perform a "hard" reset for all voices.
Definition processor.h:272
force_inline int numOwnedOutputs() const
Returns how many Output objects this Processor owns.
Definition processor.h:578
force_inline int getOversampleAmount() const
Retrieves the current oversampling factor.
Definition processor.h:334
std::vector< std::shared_ptr< Input > > owned_inputs_
Inputs owned by this Processor.
Definition processor.h:657
void plug(const Output *source)
Connects an external Output to this Processor's first input.
Definition processor.cpp:79
int connectedInputs()
Counts how many inputs are connected to a real source (not null_source_).
Definition processor.cpp:149
Output * addOutput(int oversample=1)
Creates and registers a new Output. Handles control rate vs. audio rate.
Definition processor.cpp:231
virtual void process(int num_samples)=0
Main processing function. Called by the ProcessorRouter.
force_inline Output * output(unsigned int index=0) const
Retrieves the Output pointer at a given index.
Definition processor.h:616
void setPluggingStart(int start)
Sets the position at which plugNext starts searching for an open input.
Definition processor.h:635
force_inline int numOwnedInputs() const
Returns how many Input objects this Processor owns.
Definition processor.h:571
virtual void enable(bool enable)
Enables or disables this Processor.
Definition processor.h:318
force_inline Output * ownedOutput(unsigned int index=0) const
Retrieves an owned Output pointer at a given index.
Definition processor.h:626
force_inline Input * ownedInput(unsigned int index=0) const
Retrieves an owned Input pointer at a given index.
Definition processor.h:606
virtual void unplug(const Output *source)
Removes a connection to a given Output from all inputs.
Definition processor.cpp:167
virtual void setSampleRate(int sample_rate)
Updates the sample rate of this Processor (scaled by oversampling).
Definition processor.h:285
std::shared_ptr< std::vector< Output * > > outputs_
All outputs, owned or external.
Definition processor.h:661
std::vector< std::shared_ptr< Output > > owned_outputs_
Outputs owned by this Processor.
Definition processor.h:658
force_inline bool isInputSourcePolyphonic(int index=0)
Checks if the input source at a given index is polyphonic.
Definition processor.h:597
ProcessorRouter * router_
The ProcessorRouter that manages this Processor.
Definition processor.h:663
force_inline void clearOutputBufferForReset(poly_mask reset_mask, int input_index, int output_index) const
Clears output samples for voices that are about to be reset, based on the trigger offset.
Definition processor.h:373
virtual Processor * clone() const =0
Clones this Processor for polyphonic expansion. Must be overridden by subclasses.
force_inline void router(ProcessorRouter *router)
Sets the ProcessorRouter that owns or manages this Processor.
Definition processor.h:507
virtual void init()
Called after constructor, used for any additional initialization. Subclasses can override....
Definition processor.h:258
virtual void reset(poly_mask reset_mask)
Called to reset the Processor's per-voice state (e.g., on note-on).
Definition processor.h:267
virtual void processWithInput(const poly_float *audio_in, int num_samples)
An optional processing function taking explicit input buffer. Fallback is an assertion failure (not s...
Definition processor.h:252
A specialized Processor that manages a directed graph of Processors and ensures correct processing or...
Definition processor_router.h:34
#define VITAL_ASSERT(x)
Definition common.h:11
#define force_inline
Definition common.h:23
force_inline void zeroBuffer(mono_float *buffer, int size)
Zeros a mono buffer (standard array).
Definition poly_utils.h:570
force_inline poly_float maskLoad(poly_float zero_value, poly_float one_value, poly_mask reset_mask)
Selects between two values (zero_value or one_value) based on a mask in each lane.
Definition poly_utils.h:351
Contains classes and functions used within the Vital synthesizer framework.
@ kVoiceOn
Definition common.h:77
constexpr int kMaxBufferSize
Maximum buffer size for processing.
Definition common.h:39
constexpr int kDefaultSampleRate
Default sample rate in Hz.
Definition common.h:41
poly_int poly_mask
Alias for clarity; used as a mask type in poly_float.
Definition poly_values.h:590
Represents a connection to an Output from another Processor.
Definition processor.h:128
Input()
Default constructor, initializes source to nullptr.
Definition processor.h:132
force_inline poly_float at(int i) const
Returns the sample at index i from the source buffer.
Definition processor.h:141
const Output * source
The output from which this input reads samples.
Definition processor.h:134
force_inline const poly_float & operator[](std::size_t i)
Operator[] overload for read-access to the source buffer.
Definition processor.h:150
Holds and manages a buffer of samples (poly_float) for a Processor's output.
Definition processor.h:35
void clearBuffer()
Zeros out the entire output buffer.
Definition processor.h:81
force_inline void trigger(poly_mask mask, poly_float value, poly_int offset)
Sets trigger values (mask, trigger value, and offset).
Definition processor.h:63
poly_float * buffer
Pointer to the output buffer.
Definition processor.h:110
poly_int trigger_offset
Sample offset (per voice) for triggers.
Definition processor.h:117
Processor * owner
Owning processor.
Definition processor.h:112
Output(int size=kMaxBufferSize, int max_oversample=1)
Constructs an Output with a specified buffer size and oversampling factor.
Definition processor.h:41
void ensureBufferSize(int new_max_buffer_size)
Ensures the buffer is large enough to hold new_max_buffer_size samples. This will reallocate if neces...
Definition processor.h:98
virtual ~Output()
Virtual destructor.
Definition processor.h:55
int buffer_size
Current buffer size in samples.
Definition processor.h:114
force_inline void clearTrigger()
Clears the trigger mask, value, and offset.
Definition processor.h:72
poly_mask trigger_mask
Mask for triggered voices.
Definition processor.h:115
force_inline bool isControlRate() const
Checks whether this output runs at control rate (buffer_size == 1).
Definition processor.h:89
std::unique_ptr< poly_float[]> owned_buffer
Owned memory for the output buffer.
Definition processor.h:111
poly_float trigger_value
Trigger values for voices.
Definition processor.h:116
Holds shared state regarding sample rate, oversampling, and other flags.
Definition processor.h:163
bool enabled
Whether this Processor is currently enabled or not.
Definition processor.h:178
int sample_rate
The current sample rate (may include oversampling factor).
Definition processor.h:175
int oversample_amount
Oversampling factor.
Definition processor.h:176
ProcessorState()
Default constructor, initializes to default sample rate and no oversampling.
Definition processor.h:167
bool initialized
Whether this Processor has been initialized.
Definition processor.h:179
bool control_rate
True if running at control rate (usually buffer_size == 1).
Definition processor.h:177
A specialized Output that always runs at control rate (buffer_size = 1).
Definition processor.h:189
Output()
Constructs a control-rate Output (always buffer_size = 1).
Definition processor.h:193
Represents a vector of floating-point values using SIMD instructions.
Definition poly_values.h:600
static force_inline mask_simd_type vector_call equal(simd_type one, simd_type two)
Compares two SIMD float registers for equality, element-wise.
Definition poly_values.h:954
Represents a vector of integer values using SIMD instructions.
Definition poly_values.h:56