Oscilloscope 0.5.0
A simple oscilloscope VST
Loading...
Searching...
No Matches
PluginProcessor.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file contains the basic framework code for a JUCE plugin processor.
5
6 ==============================================================================
7*/
8
9#include "PluginProcessor.h"
10#include <PluginEditor.h>
11
12//==============================================================================
14#ifndef JucePlugin_PreferredChannelConfigurations
15 : AudioProcessor(
16 BusesProperties()
17#if !JucePlugin_IsMidiEffect
18#if !JucePlugin_IsSynth
19 .withInput("Input", juce::AudioChannelSet::stereo(), true)
20#endif
21 .withOutput("Output", juce::AudioChannelSet::stereo(), true)
22#endif
23 ),
24#endif
25 processorTreeState(
26 *this, nullptr, juce::Identifier("PARAMETERS"),
27 {
28 // define TreeState parameters
29 std::make_unique<juce::AudioParameterBool>("drawGrid",
30 "Draw Grid", false),
31 std::make_unique<juce::AudioParameterFloat>(
32 "bufferLength", "Scope Length", 0.05, 1, 0.2),
33 std::make_unique<juce::AudioParameterBool>(
34 "isProfessional", "Professional View", false),
35 std::make_unique<juce::AudioParameterBool>("isTriggered",
36 "Trigger", false),
37 std::make_unique<juce::AudioParameterBool>("slopeButtonTriggered",
38 "Slope", false),
39 std::make_unique<juce::AudioParameterBool>("autoTriggered",
40 "Auto", false),
41 std::make_unique<juce::AudioParameterFloat>(
42 "triggerLevel", "Trigger Level", 0.05, 1, 0.2),
43 std::make_unique<juce::AudioParameterFloat>(
44 "decayTime", "Decay Time", 0.05, 1, static_cast<float>(0.2)),
45 std::make_unique<juce::AudioParameterBool>("muteOutput", "Mute",
46 false),
47
48 }) {
49 // Mute output if on Android (avoid feedback)
50 if (juce::SystemStats::getOperatingSystemType() ==
51 juce::SystemStats::OperatingSystemType::Android) {
52 processorTreeState.getParameter("muteOutput")->setValueNotifyingHost(true);
53 }
54
55 // reset pointers
56 audioBufferQueue.reset(
57 new AudioBufferQueue<float>(44100, getEditorRefreshRate()));
58 scopeDataCollector.reset(new ScopeDataCollector(*audioBufferQueue.get()));
59}
60
62
63void OscilloscopeAudioProcessor::resetAllValuesToDefault(juce::ValueTree tree) {
64 for (int i = 0; i < tree.getNumChildren(); ++i) {
65 juce::ValueTree child = tree.getChild(i);
66
67 // Check if the child has a default value
68 if (child.hasProperty("defaultValue")) {
69 // Reset the value to the default value
70 child.setProperty("value", child.getProperty("defaultValue"), nullptr);
71 }
72
73 // Recursively reset the values of any child
74 resetAllValuesToDefault(child);
75 }
76}
77
78//==============================================================================
79const juce::String OscilloscopeAudioProcessor::getName() const {
80 return JucePlugin_Name;
81}
82
84#if JucePlugin_WantsMidiInput
85 return true;
86#else
87 return false;
88#endif
89}
90
92#if JucePlugin_ProducesMidiOutput
93 return true;
94#else
95 return false;
96#endif
97}
98
100#if JucePlugin_IsMidiEffect
101 return true;
102#else
103 return false;
104#endif
105}
106
108
110 return 1; // NB: some hosts don't cope very well if you tell them there are 0
111 // programs, so this should be at least 1, even if you're not really
112 // implementing programs.
113}
114
116
118
119const juce::String OscilloscopeAudioProcessor::getProgramName(int index) {
120 return {};
121}
122
124 int index, const juce::String &newName) {}
125
126//==============================================================================
128 int samplesPerBlock) {
129 // store sample rate
130 this->sampleRate = sampleRate;
131
132 // reset pointers
133 audioBufferQueue.reset(new AudioBufferQueue<float>(
134 sampleRate, getEditorRefreshRate(), samplesPerBlock));
135 scopeDataCollector.reset(new ScopeDataCollector(*audioBufferQueue.get()));
136}
137
139
140#ifndef JucePlugin_PreferredChannelConfigurations
142 const BusesLayout &layouts) const {
143#if JucePlugin_IsMidiEffect
144 juce::ignoreUnused(layouts);
145 return true;
146#else
147 // This is the place where you check if the layout is supported.
148 // In this template code we only support mono or stereo.
149 // Some plugin hosts, such as certain GarageBand versions, will only
150 // load plugins that support stereo bus layouts.
151 if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono() &&
152 layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo())
153 return false;
154
155 // This checks if the input layout matches the output layout
156#if !JucePlugin_IsSynth
157 if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
158 return false;
159#endif
160
161 return true;
162#endif
163}
164#endif
165
166void OscilloscopeAudioProcessor::processBlock(juce::AudioBuffer<float> &buffer,
167 juce::MidiBuffer &midiMessages) {
168 juce::ScopedNoDenormals noDenormals;
169 auto totalNumInputChannels = getTotalNumInputChannels();
170 auto totalNumOutputChannels = getTotalNumOutputChannels();
171
172 for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
173 buffer.clear(i, 0, buffer.getNumSamples());
174
175 // collect data to plot
176 scopeDataCollector->process(buffer.getReadPointer(0),
177 (size_t)buffer.getNumSamples());
178
179 // mute output if needed
180 if (processorTreeState.getParameterAsValue("muteOutput").getValue()) {
181 buffer.applyGain(0);
182 }
183}
184
185//==============================================================================
187 return true; // (change this to false if you choose to not supply an editor)
188}
189
190juce::AudioProcessorEditor *OscilloscopeAudioProcessor::createEditor() {
191 return new OscilloscopeAudioProcessorEditor(*this);
192}
193
194//==============================================================================
196 juce::MemoryBlock &destData) {
197 // You should use this method to store your parameters in the memory block.
198 // You could do that either as raw data, or use the XML or ValueTree classes
199 // as intermediaries to make it easy to save and load complex data.
200
201 // Serialize the XmlElement object to a MemoryBlock
202 copyXmlToBinary(*processorTreeState.state.createXml().get(), destData);
203}
204
206 int sizeInBytes) {
207 // You should use this method to restore your parameters from this memory
208 // block, whose contents will have been created by the getStateInformation()
209 // call. Create an XmlElement object to hold the state Deserialize the
210 // XmlElement object from the MemoryBlock Deserialize the binary data into an
211 // XmlElement
212 std::unique_ptr<juce::XmlElement> xmlState(
213 getXmlFromBinary(data, sizeInBytes));
214 if (xmlState.get() != nullptr) {
215 // Get the child element of the XmlElement and create a ValueTree from it
216 juce::ValueTree stateTree = juce::ValueTree::fromXml(*xmlState);
217
218 // Restore the state of the AudioProcessorValueTreeState object from the
219 // ValueTree
220 processorTreeState.replaceState(stateTree);
221 }
222 xmlState.reset();
223}
224
225int OscilloscopeAudioProcessor::getSampleRate() { return this->sampleRate; }
226
228 return this->audioBufferQueue.get();
229}
230
231juce::AudioProcessorValueTreeState *OscilloscopeAudioProcessor::getTreeState() {
232 return &this->processorTreeState;
233}
234
235//==============================================================================
236// This creates new instances of the plugin..
237juce::AudioProcessor *JUCE_CALLTYPE createPluginFilter() {
238 return new OscilloscopeAudioProcessor();
239}
240
242 // get and return property value
243 auto size =
244 processorTreeState.state.getOrCreateChildWithName("lastSize", nullptr);
245 return size.getProperty("width", EDITOR_INITIAL_WIDTH());
246}
248 // get and return property value
249 auto size =
250 processorTreeState.state.getOrCreateChildWithName("lastSize", nullptr);
251 return size.getProperty("height", EDITOR_INITIAL_HEIGHT());
252}
253
255 // get child
256 auto size =
257 processorTreeState.state.getOrCreateChildWithName("lastSize", nullptr);
258
259 // store properties values
260 size.setProperty("width", width, nullptr);
261 size.setProperty("height", height, nullptr);
262}
263
265 // get child
266 auto rate = processorTreeState.state.getOrCreateChildWithName(
267 "editorRefreshRate", nullptr);
268
269 // store property value
270 return rate.getProperty("height", EDITOR_INITIAL_RATE());
271}
juce::AudioProcessor *JUCE_CALLTYPE createPluginFilter()
Oscilloscope audio processor.
const juce::String getProgramName(int index) override
juce::AudioProcessorEditor * createEditor() override
void processBlock(juce::AudioBuffer< float > &, juce::MidiBuffer &) override
bool hasEditor() const override
double getTailLengthSeconds() const override
void setCurrentProgram(int index) override
void storeEditorSize(int width, int height)
bool producesMidi() const override
const juce::String getName() const override
bool isMidiEffect() const override
void setStateInformation(const void *data, int sizeInBytes) override
juce::AudioProcessorValueTreeState * getTreeState()
void getStateInformation(juce::MemoryBlock &destData) override
void prepareToPlay(double sampleRate, int samplesPerBlock) override
bool acceptsMidi() const override
AudioBufferQueue< float > * getAudioBufferQueue()
void changeProgramName(int index, const juce::String &newName) override
bool isBusesLayoutSupported(const BusesLayout &layouts) const override