Mercurial > hg > audio_effects_textbook_code
comparison effects/reverb/Source/PluginProcessor.cpp @ 0:e32fe563e124
First commit
author | Andrew McPherson <andrewm@eecs.qmul.ac.uk> |
---|---|
date | Fri, 10 Oct 2014 15:41:23 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e32fe563e124 |
---|---|
1 /* | |
2 This code accompanies the textbook: | |
3 | |
4 Digital Audio Effects: Theory, Implementation and Application | |
5 Joshua D. Reiss and Andrew P. McPherson | |
6 | |
7 --- | |
8 | |
9 Reverb: algorithmic reverb effect based on MVerb | |
10 See textbook Chapter 11: Reverberation | |
11 | |
12 Original code by Martin Eastwood: MVerb (see MVerb.h) | |
13 Adapted for JUCE by Brecht De Man | |
14 | |
15 When using this code (or a modified version thereof) please cite: | |
16 | |
17 R. Stables, S. Enderby, B. De Man, G. Fazekas, J. D. Reiss, "SAFE: | |
18 A System for the Extraction and Retrieval of Semantic Audio | |
19 Descriptors," 15th International Society for Music Information | |
20 Retrieval Conference (ISMIR 2014), 2014. | |
21 | |
22 --- | |
23 | |
24 This program is free software: you can redistribute it and/or modify | |
25 it under the terms of the GNU General Public License as published by | |
26 the Free Software Foundation, either version 3 of the License, or | |
27 (at your option) any later version. | |
28 | |
29 This program is distributed in the hope that it will be useful, | |
30 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
32 GNU General Public License for more details. | |
33 | |
34 You should have received a copy of the GNU General Public License | |
35 along with this program. If not, see <http://www.gnu.org/licenses/>. | |
36 */ | |
37 | |
38 | |
39 #include "PluginProcessor.h" | |
40 #include "PluginEditor.h" | |
41 | |
42 #if JUCE_INTEL | |
43 #define JUCE_SNAP_TO_ZERO(n) if (! (n < -1.0e-8 || n > 1.0e-8)) n = 0; | |
44 #else | |
45 #define JUCE_SNAP_TO_ZERO(n) | |
46 #endif | |
47 | |
48 ReverbAudioProcessor::ReverbAudioProcessor() | |
49 : | |
50 _numChannels (1) | |
51 ,_numSamples (1) // dummy - will be set in prepareToPlay | |
52 ,_sampleRate (1) // dummy - will be set in prepareToPlay | |
53 ,_density (1.0) | |
54 ,_decay (1.0) | |
55 ,_size (1.0) | |
56 ,_damp (1.0) | |
57 ,_bandwidth (1.0) | |
58 ,_predelay (0.0) | |
59 ,_gain (1.0) | |
60 ,_mix (0.5) | |
61 ,_lateEarly (0.5) | |
62 ,tempInput (1,1)// dummy - will be set in prepareToPlay | |
63 ,tempOutput (1,1)// dummy - will be set in prepareToPlay | |
64 ,_lastUIWidth (850) | |
65 ,_lastUIHeight (650) | |
66 | |
67 { | |
68 // Update all parameters | |
69 for (int index = 0; index < MVerb<float>::NUM_PARAMS; ++index) | |
70 { | |
71 updateParameters(index); | |
72 } | |
73 } | |
74 | |
75 ReverbAudioProcessor::~ReverbAudioProcessor() | |
76 { | |
77 } | |
78 | |
79 //----------------------------------------------------------------------------- | |
80 // P R E P A R E T O P L A Y | |
81 void ReverbAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) | |
82 { | |
83 // If sample rate/block size changes or straight after construction | |
84 if (_numSamples != samplesPerBlock || _sampleRate != sampleRate) | |
85 { | |
86 _sampleRate = sampleRate; | |
87 _numSamples = samplesPerBlock; | |
88 _numChannels = getNumInputChannels(); | |
89 | |
90 tempInput.setSize (_numChannels,_numSamples); | |
91 tempOutput.setSize(_numChannels,_numSamples); | |
92 tempInput.clear(); | |
93 tempOutput.clear(); | |
94 | |
95 _mverb.reset(); | |
96 _mverb.setSampleRate (_sampleRate); // set reverb sample rate | |
97 } | |
98 } | |
99 | |
100 | |
101 //----------------------------------------------------------------------------- | |
102 // P R O C E S S B L O C K | |
103 void ReverbAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) | |
104 { | |
105 int numSamples = buffer.getNumSamples(); | |
106 int numChannels = buffer.getNumChannels(); | |
107 | |
108 for(int channel = 0; channel < numChannels; channel++) | |
109 { | |
110 tempInput.copyFrom (channel, 0, buffer, channel, 0, numSamples); | |
111 } | |
112 | |
113 float** input = tempInput.getArrayOfWritePointers(); | |
114 float** output = tempOutput.getArrayOfWritePointers(); | |
115 | |
116 _mverb.process (input, output, numSamples); // processing by MVerb | |
117 | |
118 for(int channel = 0; channel < numChannels; channel++) | |
119 { | |
120 buffer.copyFrom (channel, 0, output [channel], numSamples); | |
121 } | |
122 } | |
123 | |
124 | |
125 //----------------------------------------------------------------------------- | |
126 // U P D A T E P A R A M E T E R S | |
127 void ReverbAudioProcessor::updateParameters (int index) | |
128 { | |
129 switch(index) | |
130 { | |
131 case MVerb<float>::DAMPINGFREQ: | |
132 _mverb.setParameter (index, _damp); | |
133 break; | |
134 | |
135 case MVerb<float>::DENSITY: | |
136 _mverb.setParameter (index, _density); | |
137 break; | |
138 | |
139 case MVerb<float>::BANDWIDTHFREQ: | |
140 _mverb.setParameter (index, _bandwidth); | |
141 break; | |
142 | |
143 case MVerb<float>::PREDELAY: | |
144 _mverb.setParameter (index, _predelay); | |
145 break; | |
146 | |
147 case MVerb<float>::DECAY: | |
148 _mverb.setParameter (index, _decay); | |
149 break; | |
150 | |
151 case MVerb<float>::SIZE: | |
152 _mverb.setParameter (index, _size); | |
153 break; | |
154 | |
155 case MVerb<float>::GAIN: | |
156 _mverb.setParameter (index, _gain); | |
157 break; | |
158 | |
159 case MVerb<float>::MIX: | |
160 _mverb.setParameter (index, _mix); | |
161 break; | |
162 | |
163 case MVerb<float>::EARLYMIX: | |
164 _mverb.setParameter (index, _lateEarly); | |
165 break; | |
166 } | |
167 } | |
168 | |
169 | |
170 //----------------------------------------------------------------------------- | |
171 // R E S E T | |
172 void ReverbAudioProcessor::Reset() | |
173 { | |
174 _mverb.reset(); // not used | |
175 } | |
176 | |
177 | |
178 //----------------------------------------------------------------------------- | |
179 // | |
180 void ReverbAudioProcessor::releaseResources() | |
181 { | |
182 // When playback stops, you can use this to free up any spare memory, etc. | |
183 } | |
184 | |
185 | |
186 bool ReverbAudioProcessor::hasEditor() const | |
187 { | |
188 return true; // (change this to false if you choose to not supply an editor) | |
189 } | |
190 | |
191 AudioProcessorEditor* ReverbAudioProcessor::createEditor() | |
192 { | |
193 return new ReverbAudioProcessorEditor (this); | |
194 } | |
195 | |
196 | |
197 //============================================================================== | |
198 void ReverbAudioProcessor::getStateInformation (MemoryBlock& destData) | |
199 { | |
200 // SAVE STATE INFO | |
201 XmlElement xml("JRAMReverb_XML"); | |
202 | |
203 // Knobs | |
204 xml.setAttribute("_density" ,_density); | |
205 xml.setAttribute("_decay" ,_decay); | |
206 xml.setAttribute("_size" ,_size); | |
207 xml.setAttribute("_damp" ,_damp); | |
208 xml.setAttribute("_bandwidth" ,_bandwidth); | |
209 xml.setAttribute("_predelay" ,_predelay); | |
210 xml.setAttribute("_gain" ,_gain); | |
211 xml.setAttribute("_mix" ,_mix); | |
212 xml.setAttribute("_lateEarly" ,_lateEarly); | |
213 | |
214 | |
215 // then use this helper function to stuff it into the binary blob and return it.. | |
216 copyXmlToBinary(xml, destData); | |
217 } | |
218 | |
219 void ReverbAudioProcessor::setStateInformation (const void* data, int sizeInBytes) | |
220 { | |
221 // LOAD STATE INFO | |
222 ScopedPointer<XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes)); | |
223 | |
224 // make sure that it's actually our type of XML object.. | |
225 if(xmlState->hasTagName("JRAMReverb_XML")) | |
226 { | |
227 // Knobs | |
228 _density = (float) xmlState->getDoubleAttribute("_density",true); | |
229 _decay = (float) xmlState->getDoubleAttribute("_decay",true); | |
230 _size = (float) xmlState->getDoubleAttribute("_size",true); | |
231 _damp = (float) xmlState->getDoubleAttribute("_damp",true); | |
232 _bandwidth = (float) xmlState->getDoubleAttribute("_bandwidth",true); | |
233 _predelay = (float) xmlState->getDoubleAttribute("_predelay",true); | |
234 _gain = (float) xmlState->getDoubleAttribute("_gain",true); | |
235 _mix = (float) xmlState->getDoubleAttribute("_mix",true); | |
236 _lateEarly = (float) xmlState->getDoubleAttribute("_lateEarly",true); | |
237 } | |
238 } | |
239 | |
240 // This creates new instances of the plugin.. | |
241 AudioProcessor* JUCE_CALLTYPE createPluginFilter() | |
242 { | |
243 return new ReverbAudioProcessor(); | |
244 } | |
245 | |
246 const String ReverbAudioProcessor::getName() const | |
247 { | |
248 return JucePlugin_Name; | |
249 } | |
250 | |
251 bool ReverbAudioProcessor::silenceInProducesSilenceOut() const | |
252 { | |
253 return true; | |
254 } | |
255 | |
256 int ReverbAudioProcessor::getNumParameters() | |
257 { | |
258 return MVerb<float>::NUM_PARAMS; | |
259 } | |
260 | |
261 float ReverbAudioProcessor::getParameter (int index) // externally accessible | |
262 { | |
263 switch (index) | |
264 { | |
265 case MVerb<float>::DENSITY: return GetDensity(); | |
266 case MVerb<float>::DECAY: return GetDecay(); | |
267 case MVerb<float>::SIZE: return GetSize(); | |
268 case MVerb<float>::DAMPINGFREQ: return GetDamp(); | |
269 case MVerb<float>::BANDWIDTHFREQ: return GetBandwidth(); | |
270 case MVerb<float>::PREDELAY: return GetPredelay(); | |
271 case MVerb<float>::GAIN: return GetGain(); | |
272 case MVerb<float>::MIX: return GetMix(); | |
273 case MVerb<float>::EARLYMIX: return GetLateEarly(); | |
274 default: return 0.0f; | |
275 } | |
276 } | |
277 | |
278 void ReverbAudioProcessor::setParameter (int index, float newValue) // externally accessible | |
279 { | |
280 switch (index) | |
281 { | |
282 case MVerb<float>::DENSITY: | |
283 SetDensity(newValue); | |
284 break; | |
285 case MVerb<float>::DECAY: | |
286 SetDecay(newValue); | |
287 break; | |
288 case MVerb<float>::SIZE: | |
289 SetSize(newValue); | |
290 break; | |
291 case MVerb<float>::DAMPINGFREQ: | |
292 SetDamp(newValue); | |
293 break; | |
294 case MVerb<float>::BANDWIDTHFREQ: | |
295 SetBandwidth(newValue); | |
296 break; | |
297 case MVerb<float>::PREDELAY: | |
298 SetPredelay(newValue); | |
299 break; | |
300 case MVerb<float>::GAIN: | |
301 SetGain(newValue); | |
302 break; | |
303 case MVerb<float>::MIX: | |
304 SetMix(newValue); | |
305 break; | |
306 case MVerb<float>::EARLYMIX: | |
307 SetLateEarly(newValue); | |
308 break; | |
309 default: | |
310 break; | |
311 } | |
312 } | |
313 | |
314 const String ReverbAudioProcessor::getParameterName (int index) // externally accessible | |
315 { | |
316 switch (index) | |
317 { | |
318 case MVerb<float>::DENSITY: return "Density"; | |
319 case MVerb<float>::DECAY: return "Decay"; | |
320 case MVerb<float>::SIZE: return "Size"; | |
321 case MVerb<float>::DAMPINGFREQ: return "Damp"; | |
322 case MVerb<float>::BANDWIDTHFREQ: return "Bandwidth"; | |
323 case MVerb<float>::PREDELAY: return "Predelay"; | |
324 case MVerb<float>::GAIN: return "Gain"; | |
325 case MVerb<float>::MIX: return "Mix"; | |
326 case MVerb<float>::EARLYMIX: return "Late vs. early reflections"; | |
327 default: break; | |
328 } | |
329 return String::empty; | |
330 } | |
331 | |
332 const String ReverbAudioProcessor::getParameterText (int index) | |
333 { | |
334 return String (getParameter (index), 2); | |
335 } | |
336 | |
337 const String ReverbAudioProcessor::getInputChannelName (int channelIndex) const | |
338 { | |
339 return String (channelIndex + 1); | |
340 } | |
341 | |
342 const String ReverbAudioProcessor::getOutputChannelName (int channelIndex) const | |
343 { | |
344 return String (channelIndex + 1); | |
345 } | |
346 | |
347 bool ReverbAudioProcessor::isInputChannelStereoPair (int index) const | |
348 { | |
349 return true; | |
350 } | |
351 | |
352 bool ReverbAudioProcessor::isOutputChannelStereoPair (int index) const | |
353 { | |
354 return true; | |
355 } | |
356 | |
357 bool ReverbAudioProcessor::acceptsMidi() const | |
358 { | |
359 #if JucePlugin_WantsMidiInput | |
360 return true; | |
361 #else | |
362 return false; | |
363 #endif | |
364 } | |
365 | |
366 bool ReverbAudioProcessor::producesMidi() const | |
367 { | |
368 #if JucePlugin_ProducesMidiOutput | |
369 return true; | |
370 #else | |
371 return false; | |
372 #endif | |
373 } | |
374 | |
375 int ReverbAudioProcessor::getNumPrograms() | |
376 { | |
377 return 0; | |
378 } | |
379 | |
380 int ReverbAudioProcessor::getCurrentProgram() | |
381 { | |
382 return 0; | |
383 } | |
384 | |
385 void ReverbAudioProcessor::setCurrentProgram (int index) | |
386 { | |
387 } | |
388 | |
389 const String ReverbAudioProcessor::getProgramName (int index) | |
390 { | |
391 return String::empty; | |
392 } | |
393 | |
394 void ReverbAudioProcessor::changeProgramName (int index, const String& newName) | |
395 { | |
396 } |