WE Core
Loading...
Searching...
No Matches
CoreAudioProcessor.h
Go to the documentation of this file.
1/*
2 * File: CoreAudioProcessor.h
3 *
4 * Version: 1.0.0
5 *
6 * Created: 10/06/2017
7 *
8 * This file is part of WECore.
9 *
10 * WECore is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * WECore is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with WECore. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#pragma once
26
27#include "../JuceLibraryCode/JuceHeader.h"
30#include "CustomParameter.h"
31
33
41 class CoreAudioProcessor : public juce::AudioProcessor,
43 public:
44 inline CoreAudioProcessor();
45 inline CoreAudioProcessor(const BusesProperties& ioLayouts);
46 inline virtual ~CoreAudioProcessor();
47
52 inline void setParameterValueInternal(juce::AudioParameterFloat* param, float value);
53 inline void setParameterValueInternal(juce::AudioParameterInt* param, int value);
54 inline void setParameterValueInternal(juce::AudioParameterBool* param, bool value);
60 void addParameterChangeListener(juce::ChangeListener* listener) {
61 _parameterBroadcaster.addChangeListener(listener);
62 }
63
67 void removeParameterChangeListener(juce::ChangeListener* listener) {
68 _parameterBroadcaster.removeChangeListener(listener);
69 }
70
74 inline virtual void getStateInformation(juce::MemoryBlock& destData) override;
75
85 inline std::unique_ptr<juce::XmlElement> writeToXml();
86
90 inline virtual void setStateInformation(const void* data, int sizeInBytes) override;
91
95 inline void restoreFromXml(std::unique_ptr<juce::XmlElement> element);
96
97 protected:
110 inline void registerParameter(juce::AudioParameterFloat*& param,
111 const juce::String& name,
113 float defaultValue,
114 float precision);
115
116 inline void registerParameter(juce::AudioParameterFloat*& param,
117 const juce::String& name,
119 float defaultValue,
120 float precision);
121
122 inline void registerParameter(juce::AudioParameterInt*& param,
123 const juce::String& name,
125 int defaultValue);
126
127 inline void registerParameter(juce::AudioParameterBool*& param,
128 const juce::String& name,
129 bool defaultValue);
152 inline void registerPrivateParameter(juce::AudioParameterFloat*& param,
153 const juce::String& name,
155 float defaultValue,
156 float precision,
157 std::function<void(float)> setter);
158
159 inline void registerPrivateParameter(juce::AudioParameterInt*& param,
160 const juce::String& name,
162 int defaultValue,
163 std::function<void(int)> setter);
164
165 template <typename PARAM_TYPE>
166 inline void registerPrivateParameter(PARAM_TYPE*& param, const juce::String& name);
173 virtual std::vector<juce::String> _provideParamNamesForMigration() = 0;
174
178 virtual void _migrateParamValues(std::vector<float>& paramValues) = 0;
179
180 private:
181
182 // Increment this after changing how parameter states are stored
183 static constexpr int PARAMS_SCHEMA_VERSION {1};
184
185 // We need to store pointers to all the private parameters that are registered so that they
186 // can be deallocated by the destructor
187 std::vector<juce::AudioProcessorParameter*> _privateParameters;
188 std::vector<CustomParameter*> _customParameters;
189
195 juce::String name;
196 std::function<float()> getter;
197 std::function<void(float)> setter;
198 };
199
206 juce::String name;
207 std::function<void(juce::XmlElement*)> writeToXml;
208 std::function<void(juce::XmlElement*)> restoreFromXml;
209 };
210
215 class ParameterBroadcaster : public juce::AudioProcessorParameter::Listener,
216 public juce::ChangeBroadcaster {
217 public:
219 virtual ~ParameterBroadcaster() = default;
220
221 virtual void parameterValueChanged(int /*parameterIndex*/, float /*newValue*/) override {
222 this->sendChangeMessage();
223 }
224
225 virtual void parameterGestureChanged(int /*parameterIndex*/, bool /*gestureIsStarting*/) override {}
226 };
227
229
233 std::vector<ParameterInterface> _paramsList;
234 std::vector<CustomParameterInterface> _customParamsList;
235
236 inline std::vector<float> _stringToFloatVector(const juce::String sFloatCSV) const;
237
238 inline std::unique_ptr<juce::XmlElement> _migrateParameters(
239 std::unique_ptr<juce::XmlElement> rootElement);
240
241 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CoreAudioProcessor)
242 };
243
247
248 CoreAudioProcessor::CoreAudioProcessor(const BusesProperties& ioLayouts) : juce::AudioProcessor(ioLayouts) {
250 }
251
253 for (juce::AudioProcessorParameter* parameter : _privateParameters) {
254 delete parameter;
255 }
256
257 for (CustomParameter* parameter : _customParameters) {
258 delete parameter;
259 }
260 }
261
262 void CoreAudioProcessor::setParameterValueInternal(juce::AudioParameterFloat* param, float value) {
263 param->setValueNotifyingHost(param->getNormalisableRange().convertTo0to1(value));
264 }
265
266 void CoreAudioProcessor::setParameterValueInternal(juce::AudioParameterInt* param, int value) {
267 param->setValueNotifyingHost(param->getNormalisableRange().convertTo0to1(value));
268 }
269
270 void CoreAudioProcessor::setParameterValueInternal(juce::AudioParameterBool* param, bool value) {
271 param->setValueNotifyingHost(value);
272 }
273
274 void CoreAudioProcessor::getStateInformation(juce::MemoryBlock& destData) {
275 std::unique_ptr<juce::XmlElement> element = writeToXml();
276 copyXmlToBinary(*element.get(), destData);
277 }
278
279 std::unique_ptr<juce::XmlElement> CoreAudioProcessor::writeToXml() {
280 auto rootElement = std::make_unique<juce::XmlElement>("Root");
281
282 // Set the XML params version
283 rootElement->setAttribute("SchemaVersion", PARAMS_SCHEMA_VERSION);
284
285 // Store the parameters
286 juce::XmlElement* paramsElement = rootElement->createNewChildElement("Params");
287 for (const ParameterInterface& param : _paramsList) {
288 paramsElement->setAttribute(param.name, param.getter());
289 }
290
291 for (const CustomParameterInterface& param : _customParamsList) {
292 juce::XmlElement* thisParameterElement = paramsElement->createNewChildElement(param.name);
293 param.writeToXml(thisParameterElement);
294 }
295
296 return rootElement;
297 }
298
299 void CoreAudioProcessor::setStateInformation(const void* data, int sizeInBytes) {
300 std::unique_ptr<juce::XmlElement> element(getXmlFromBinary(data, sizeInBytes));
301 restoreFromXml(std::move(element));
302 }
303
304 void CoreAudioProcessor::restoreFromXml(std::unique_ptr<juce::XmlElement> element) {
305 // Parse the XML
306 if (element != nullptr) {
307
308 // If state was saved using an old plugin we need to migrate the XML data
309 if (element->getIntAttribute("SchemaVersion", 0) < PARAMS_SCHEMA_VERSION) {
310 element = _migrateParameters(std::move(element));
311 }
312
313 // Iterate through our list of parameters, restoring them from the XML attributes
314 juce::XmlElement* paramsElement = element->getChildByName("Params");
315 if (paramsElement != nullptr) {
316 for (const ParameterInterface& param : _paramsList) {
317 if (paramsElement->hasAttribute(param.name)) {
318 param.setter(static_cast<float>(paramsElement->getDoubleAttribute(param.name)));
319 }
320 }
321
322 for (const CustomParameterInterface& param : _customParamsList) {
323 juce::XmlElement* thisParameterElement = paramsElement->getChildByName(param.name);
324
325 if (thisParameterElement != nullptr) {
326 param.restoreFromXml(thisParameterElement);
327 }
328 }
329 }
330 }
331 }
332
333 void CoreAudioProcessor::registerParameter(juce::AudioParameterFloat*& param,
334 const juce::String& name,
336 float defaultValue,
337 float precision) {
338 param = new juce::AudioParameterFloat(name, name, {static_cast<float>(range->minValue), static_cast<float>(range->maxValue), precision}, defaultValue);
339
340 ParameterInterface interface = {name,
341 [&param]() { return param->get(); },
342 [&](float val) { setParameterValueInternal(param, val); }};
343 _paramsList.push_back(interface);
344
345 param->addListener(&_parameterBroadcaster);
346 addParameter(param);
347 }
348
349 void CoreAudioProcessor::registerParameter(juce::AudioParameterFloat*& param,
350 const juce::String& name,
352 float defaultValue,
353 float precision) {
354 param = new juce::AudioParameterFloat(name, name, {static_cast<float>(range->minValue), static_cast<float>(range->maxValue), precision}, defaultValue);
355
356 ParameterInterface interface = {name,
357 [&param]() { return param->get(); },
358 [&](float val) { setParameterValueInternal(param, val); }};
359 _paramsList.push_back(interface);
360
361 param->addListener(&_parameterBroadcaster);
362 addParameter(param);
363 }
364
365 void CoreAudioProcessor::registerParameter(juce::AudioParameterInt*& param,
366 const juce::String& name,
368 int defaultValue) {
369 param = new juce::AudioParameterInt(name, name, range->minValue, range->maxValue, defaultValue);
370
371 ParameterInterface interface = {name,
372 [&param]() { return param->get(); },
373 [&](float val) { setParameterValueInternal(param, static_cast<int>(val)); }};
374 _paramsList.push_back(interface);
375
376 param->addListener(&_parameterBroadcaster);
377 addParameter(param);
378 }
379
380 void CoreAudioProcessor::registerParameter(juce::AudioParameterBool*& param,
381 const juce::String& name,
382 bool defaultValue) {
383 param = new juce::AudioParameterBool(name, name, defaultValue);
384
385 ParameterInterface interface = {name,
386 [&param]() { return param->get(); },
387 [&](float val) { setParameterValueInternal(param, static_cast<bool>(val)); }};
388 _paramsList.push_back(interface);
389
390 param->addListener(&_parameterBroadcaster);
391 addParameter(param);
392 }
393
394 void CoreAudioProcessor::registerPrivateParameter(juce::AudioParameterFloat*& param,
395 const juce::String& name,
397 float defaultValue,
398 float precision,
399 std::function<void(float)> setter) {
400 param = new juce::AudioParameterFloat(name, name, {static_cast<float>(range->minValue), static_cast<float>(range->maxValue), precision}, defaultValue);
401
402 ParameterInterface interface = {name,
403 [&param]() { return param->get(); },
404 [setter](float val) { setter(val); }};
405 _paramsList.push_back(interface);
406
407 param->addListener(&_parameterBroadcaster);
408 _privateParameters.push_back(param);
409 }
410
411 void CoreAudioProcessor::registerPrivateParameter(juce::AudioParameterInt*& param,
412 const juce::String& name,
414 int defaultValue,
415 std::function<void(int)> setter) {
416 param = new juce::AudioParameterInt(name, name, range->minValue, range->maxValue, defaultValue);
417
418 ParameterInterface interface = {name,
419 [&param]() { return param->get(); },
420 [setter](float val) { setter(static_cast<int>(val)); }};
421 _paramsList.push_back(interface);
422
423 param->addListener(&_parameterBroadcaster);
424 _privateParameters.push_back(param);
425 }
426
427 template <typename PARAM_TYPE>
428 void CoreAudioProcessor::registerPrivateParameter(PARAM_TYPE*& param, const juce::String& name) {
429 param = new PARAM_TYPE();
430
431 CustomParameterInterface interface = {name,
432 [&param](juce::XmlElement* element) { param->writeToXml(element); },
433 [&param](juce::XmlElement* element) { param->restoreFromXml(element); }};
434 _customParamsList.push_back(interface);
435
436 param->setListener(&_parameterBroadcaster);
437 _customParameters.push_back(param);
438 }
439
440 std::vector<float> CoreAudioProcessor::_stringToFloatVector(const juce::String sFloatCSV) const {
441 juce::StringArray tokenizer;
442 tokenizer.addTokens(sFloatCSV, ",","");
443
444 std::vector<float> values;
445
446 for (int iii {0}; iii < tokenizer.size(); iii++) {
447 values.push_back(tokenizer[iii].getFloatValue());
448 }
449
450 return values;
451 }
452
453 std::unique_ptr<juce::XmlElement> CoreAudioProcessor::_migrateParameters(std::unique_ptr<juce::XmlElement> rootElement) {
454 const int schemaVersion {rootElement->getIntAttribute("SchemaVersion", 0)};
455
456 std::unique_ptr<juce::XmlElement> retVal = std::make_unique<juce::XmlElement>("Root");
457
458 if (schemaVersion == 0) {
459 // This is an original parameter schema - parameters are normalised values in a single string
460
461 forEachXmlChildElement((*rootElement), childElement) {
462 if (childElement->hasTagName("AllUserParam")) {
463
464 // Read the values into a float array
465 juce::String sFloatCSV = childElement->getAllSubText();
466 std::vector<float> readParamValues = _stringToFloatVector(sFloatCSV);
467 _migrateParamValues(readParamValues);
468
469 std::vector<juce::String> paramNames = _provideParamNamesForMigration();
470
471 juce::XmlElement* paramsElement = retVal->createNewChildElement("Params");
472
473 for (size_t idx {0}; idx < paramNames.size(); idx++) {
474 if (idx < readParamValues.size()) {
475 paramsElement->setAttribute(paramNames[idx], readParamValues[idx]);
476 }
477 }
478 }
479 }
480 }
481
482 return retVal;
483 }
484}
virtual std::vector< juce::String > _provideParamNamesForMigration()=0
std::vector< ParameterInterface > _paramsList
virtual void _migrateParamValues(std::vector< float > &paramValues)=0
void setParameterValueInternal(juce::AudioParameterFloat *param, float value)
std::vector< CustomParameter * > _customParameters
std::unique_ptr< juce::XmlElement > _migrateParameters(std::unique_ptr< juce::XmlElement > rootElement)
virtual void setStateInformation(const void *data, int sizeInBytes) override
void addParameterChangeListener(juce::ChangeListener *listener)
void restoreFromXml(std::unique_ptr< juce::XmlElement > element)
std::unique_ptr< juce::XmlElement > writeToXml()
void registerPrivateParameter(juce::AudioParameterFloat *&param, const juce::String &name, const ParameterDefinition::RangedParameter< double > *range, float defaultValue, float precision, std::function< void(float)> setter)
std::vector< juce::AudioProcessorParameter * > _privateParameters
virtual void getStateInformation(juce::MemoryBlock &destData) override
void removeParameterChangeListener(juce::ChangeListener *listener)
std::vector< float > _stringToFloatVector(const juce::String sFloatCSV) const
std::vector< CustomParameterInterface > _customParamsList
void registerParameter(juce::AudioParameterFloat *&param, const juce::String &name, const ParameterDefinition::RangedParameter< double > *range, float defaultValue, float precision)