Vital
Loading...
Searching...
No Matches
synth_plugin.cpp
Go to the documentation of this file.
1/*
2Summary:
3
4SynthPlugin is the core plugin class handling parameter management, saving/loading state, preparing audio processing, and communicating with the host. It integrates the synth engine, GUI interface, and handles parameter automation through ValueBridge instances. It also ensures that parameter changes and preset loading are communicated effectively to the GUI and host.
5 */
6
7#include "synth_plugin.h"
8#include "synth_editor.h"
9#include "sound_engine.h"
10#include "load_save.h"
11
13 last_seconds_time_ = 0.0;
14
15 // Register and create ValueBridges for all parameters.
16 int num_params = vital::Parameters::getNumParameters();
17 for (int i = 0; i < num_params; ++i) {
19 if (controls_.count(details->name) == 0)
20 continue;
21
22 // Create a ValueBridge for each known parameter.
23 ValueBridge* bridge = new ValueBridge(details->name, controls_[details->name]);
24 bridge->setListener(this);
25 bridge_lookup_[details->name] = bridge;
26 addParameter(bridge);
27 }
28
29 bypass_parameter_ = bridge_lookup_["bypass"];
30}
31
33 midi_manager_ = nullptr;
34 keyboard_state_ = nullptr;
35}
36
38 // Return the active GUI interface if available.
39 AudioProcessorEditor* editor = getActiveEditor();
40 if (editor)
41 return dynamic_cast<SynthGuiInterface*>(editor);
42 return nullptr;
43}
44
45void SynthPlugin::beginChangeGesture(const std::string& name) {
46 // Begin host automation gesture for the parameter if available.
47 if (bridge_lookup_.count(name))
48 bridge_lookup_[name]->beginChangeGesture();
49}
50
51void SynthPlugin::endChangeGesture(const std::string& name) {
52 // End host automation gesture for the parameter if available.
53 if (bridge_lookup_.count(name))
54 bridge_lookup_[name]->endChangeGesture();
55}
56
57void SynthPlugin::setValueNotifyHost(const std::string& name, vital::mono_float value) {
58 // Sets parameter value and notifies host if found.
59 if (bridge_lookup_.count(name)) {
60 vital::mono_float plugin_value = bridge_lookup_[name]->convertToPluginValue(value);
61 bridge_lookup_[name]->setValueNotifyHost(plugin_value);
62 }
63}
64
65const CriticalSection& SynthPlugin::getCriticalSection() {
66 // Return the callback lock for thread safety.
67 return getCallbackLock();
68}
69
71 // Suspend or resume processing.
72 suspendProcessing(pause);
73}
74
75const String SynthPlugin::getName() const {
76 return JucePlugin_Name;
77}
78
79const String SynthPlugin::getInputChannelName(int channel_index) const {
80 return String(channel_index + 1);
81}
82
83const String SynthPlugin::getOutputChannelName(int channel_index) const {
84 return String(channel_index + 1);
85}
86
88 return true;
89}
90
92 return true;
93}
94
96#if JucePlugin_WantsMidiInput
97 return true;
98#else
99 return false;
100#endif
101}
102
104#if JucePlugin_ProducesMidiOutput
105 return true;
106#else
107 return false;
108#endif
109}
110
112 return false;
113}
114
116 return 0.0;
117}
118
119const String SynthPlugin::getProgramName(int index) {
120 // Return current preset name if GUI and synth are available.
122 if (editor == nullptr || editor->getSynth() == nullptr)
123 return "";
124
125 return editor->getSynth()->getPresetName();
126}
127
128void SynthPlugin::prepareToPlay(double sample_rate, int buffer_size) {
129 // Prepare the synth engine and managers for playback.
130 engine_->setSampleRate(sample_rate);
131 engine_->updateAllModulationSwitches();
132 midi_manager_->setSampleRate(sample_rate);
133}
134
136 // Free resources if needed (not implemented here).
137}
138
139void SynthPlugin::processBlock(AudioSampleBuffer& buffer, MidiBuffer& midi_messages) {
140 static constexpr double kSecondsPerMinute = 60.0f;
141
142 // Check if bypassed
143 if (bypass_parameter_->getValue()) {
144 processBlockBypassed(buffer, midi_messages);
145 return;
146 }
147
148 int total_samples = buffer.getNumSamples();
149 int num_channels = getTotalNumOutputChannels();
150 AudioPlayHead* play_head = getPlayHead();
151 if (play_head) {
152 play_head->getCurrentPosition(position_info_);
153 if (position_info_.bpm)
154 engine_->setBpm(position_info_.bpm);
155
156 if (position_info_.isPlaying) {
157 double bps = position_info_.bpm / kSecondsPerMinute;
158 last_seconds_time_ = position_info_.ppqPosition / bps;
159 }
160 }
161
163 if (total_samples)
164 processKeyboardEvents(midi_messages, total_samples);
165
166 double sample_time = 1.0 / AudioProcessor::getSampleRate();
167 for (int sample_offset = 0; sample_offset < total_samples;) {
168 int num_samples = std::min<int>(total_samples - sample_offset, vital::kMaxBufferSize);
169
170 engine_->correctToTime(last_seconds_time_);
171 processMidi(midi_messages, sample_offset, sample_offset + num_samples);
172 processAudio(&buffer, num_channels, num_samples, sample_offset);
173
174 last_seconds_time_ += num_samples * sample_time;
175 sample_offset += num_samples;
176 }
177}
178
180 return true;
181}
182
183AudioProcessorEditor* SynthPlugin::createEditor() {
184 // Create the main GUI editor.
185 return new SynthEditor(*this);
186}
187
189 // Parameter changed from an external source, update synth parameters.
190 valueChangedExternal(name, value);
191}
192
193void SynthPlugin::getStateInformation(MemoryBlock& dest_data) {
194 // Save current state to JSON and then to the memory block.
195 json data = LoadSave::stateToJson(this, getCallbackLock());
196 data["tuning"] = getTuning()->stateToJson();
197
198 String data_string = data.dump();
199 MemoryOutputStream stream;
200 stream.writeString(data_string);
201 dest_data.append(stream.getData(), stream.getDataSize());
202}
203
204void SynthPlugin::setStateInformation(const void* data, int size_in_bytes) {
205 // Restore plugin state from JSON data.
206 MemoryInputStream stream(data, size_in_bytes, false);
207 String data_string = stream.readEntireStreamAsString();
208
209 pauseProcessing(true);
210 try {
211 json json_data = json::parse(data_string.toStdString());
212 LoadSave::jsonToState(this, save_info_, json_data);
213
214 if (json_data.count("tuning"))
215 getTuning()->jsonToState(json_data["tuning"]);
216 }
217 catch (const json::exception& e) {
218 std::string error = "There was an error open the preset. Preset file is corrupted.";
219 AlertWindow::showNativeDialogBox("Error opening preset", error, false);
220 }
221 pauseProcessing(false);
222
224 if (editor)
225 editor->updateFullGui();
226}
227
228AudioProcessor* JUCE_CALLTYPE createPluginFilter() {
229 return new SynthPlugin();
230}
static json stateToJson(SynthBase *synth, const CriticalSection &critical_section)
Converts the state of a given SynthBase to JSON.
Definition load_save.cpp:78
static bool jsonToState(SynthBase *synth, std::map< std::string, String > &save_info, json state)
Loads a JSON state into the given SynthBase, applying older version updates if necessary.
Definition load_save.cpp:1011
void processKeyboardEvents(MidiBuffer &buffer, int num_samples)
Processes keyboard events from a MidiBuffer, integrating them with the MidiKeyboardState.
Definition synth_base.cpp:604
void valueChangedExternal(const std::string &name, vital::mono_float value)
Handles external (non-GUI, non-MIDI) value changes to parameters.
Definition synth_base.cpp:92
Tuning * getTuning()
Returns a pointer to the synth's Tuning object.
Definition synth_base.h:554
std::unique_ptr< MidiManager > midi_manager_
Definition synth_base.h:700
std::unique_ptr< MidiKeyboardState > keyboard_state_
Definition synth_base.h:701
vital::control_map controls_
Definition synth_base.h:718
void processAudio(AudioSampleBuffer *buffer, int channels, int samples, int offset)
Processes audio into the given buffer. May be overridden or extended by subclasses.
Definition synth_base.cpp:564
std::map< std::string, String > save_info_
Definition synth_base.h:717
void processMidi(MidiBuffer &buffer, int start_sample=0, int end_sample=0)
Processes MIDI messages from a MidiBuffer, applying them to the engine’s sound generation.
Definition synth_base.cpp:595
String getPresetName()
Gets the current preset’s name.
Definition synth_base.cpp:713
std::unique_ptr< vital::SoundEngine > engine_
Definition synth_base.h:699
void processModulationChanges()
Processes pending modulation changes and updates the engine accordingly.
Definition synth_base.cpp:608
The main editor component for the SynthPlugin audio processor.
Definition synth_editor.h:24
An interface class linking the Vital synthesizer backend (SynthBase) with a GUI.
Definition synth_gui_interface.h:56
SynthBase * getSynth()
Returns the SynthBase instance this interface is managing.
Definition synth_gui_interface.h:85
virtual void updateFullGui()
Updates the entire GUI to reflect the current synth state.
Definition synth_gui_interface.cpp:62
An AudioProcessor implementation for a synthesizer plugin.
Definition synth_plugin.h:26
void parameterChanged(std::string name, vital::mono_float value) override
Called when a parameter changes externally via a ValueBridge.
Definition synth_plugin.cpp:188
void processBlock(AudioSampleBuffer &, MidiBuffer &) override
Process audio and MIDI data each block.
Definition synth_plugin.cpp:139
void endChangeGesture(const std::string &name) override
Ends a parameter change gesture for the specified parameter.
Definition synth_plugin.cpp:51
void setStateInformation(const void *data, int size_in_bytes) override
Restores the plugin state from a memory block.
Definition synth_plugin.cpp:204
void prepareToPlay(double sample_rate, int buffer_size) override
Prepare the plugin to play with the given sample rate and buffer size.
Definition synth_plugin.cpp:128
bool acceptsMidi() const override
Checks if the plugin accepts MIDI input.
Definition synth_plugin.cpp:95
void releaseResources() override
Release any resources allocated for playback.
Definition synth_plugin.cpp:135
bool silenceInProducesSilenceOut() const override
Checks if silence in leads to silence out.
Definition synth_plugin.cpp:111
const String getOutputChannelName(int channel_index) const override
Returns the output channel name.
Definition synth_plugin.cpp:83
AudioProcessorEditor * createEditor() override
Creates and returns the AudioProcessorEditor for this plugin.
Definition synth_plugin.cpp:183
bool producesMidi() const override
Checks if the plugin produces MIDI output.
Definition synth_plugin.cpp:103
void beginChangeGesture(const std::string &name) override
Begins a parameter change gesture for the specified parameter.
Definition synth_plugin.cpp:45
void getStateInformation(MemoryBlock &destData) override
Saves the plugin state to a memory block.
Definition synth_plugin.cpp:193
void setValueNotifyHost(const std::string &name, vital::mono_float value) override
Sets a parameter value and notifies the host.
Definition synth_plugin.cpp:57
const String getInputChannelName(int channel_index) const override
Returns the input channel name.
Definition synth_plugin.cpp:79
const String getProgramName(int index) override
Gets the name of a program.
Definition synth_plugin.cpp:119
bool isInputChannelStereoPair(int index) const override
Checks if the given input channel forms a stereo pair.
Definition synth_plugin.cpp:87
bool hasEditor() const override
Checks if the plugin has an editor.
Definition synth_plugin.cpp:179
SynthGuiInterface * getGuiInterface() override
Returns the GUI interface for this plugin.
Definition synth_plugin.cpp:37
const CriticalSection & getCriticalSection() override
Returns the CriticalSection for thread synchronization.
Definition synth_plugin.cpp:65
virtual ~SynthPlugin()
Destructor, cleans up allocated resources.
Definition synth_plugin.cpp:32
bool isOutputChannelStereoPair(int index) const override
Checks if the given output channel forms a stereo pair.
Definition synth_plugin.cpp:91
void pauseProcessing(bool pause) override
Pauses or resumes audio processing.
Definition synth_plugin.cpp:70
const String getName() const override
Returns the name of the plugin.
Definition synth_plugin.cpp:75
SynthPlugin()
Constructs the SynthPlugin.
Definition synth_plugin.cpp:12
double getTailLengthSeconds() const override
Gets the plugin's tail length in seconds.
Definition synth_plugin.cpp:115
json stateToJson() const
Saves the current tuning state into a JSON object.
Definition tuning.cpp:387
void jsonToState(const json &data)
Restores the tuning state from a JSON object.
Definition tuning.cpp:410
A parameter bridge that connects a vital::Value to an AudioProcessorParameter, allowing the host to m...
Definition value_bridge.h:17
float getValue() const override
Gets the current normalized (0.0 to 1.0) value of the parameter.
Definition value_bridge.h:68
void setListener(Listener *listener)
Sets a listener to receive parameter change callbacks.
Definition value_bridge.h:94
static int getNumParameters()
Definition synth_parameters.h:204
static const ValueDetails & getDetails(const std::string &name)
Definition synth_parameters.h:200
nlohmann::json json
Definition line_generator.h:7
constexpr int kMaxBufferSize
Maximum buffer size for processing.
Definition common.h:39
float mono_float
Definition common.h:33
Holds metadata about a single parameter (control) in the Vital synthesizer.
Definition synth_parameters.h:23
std::string name
Unique parameter name/identifier.
Definition synth_parameters.h:38
AudioProcessor *JUCE_CALLTYPE createPluginFilter()
Definition synth_plugin.cpp:228