Mercurial > hg > audio_effects_textbook_code
view effects/reverb/Source/PluginProcessor.cpp @ 1:04e171d2a747 tip
JUCE 4 compatible. Standardised paths on Mac: modules '../../juce/modules'; VST folder '~/SDKs/vstsdk2.4' (JUCE default). Replaced deprecated 'getSampleData(channel)'; getToggleState(...); setToggleState(...); setSelectedId(...). Removed unused variables. Ignore JUCE code and build files.
author | Brecht De Man <b.deman@qmul.ac.uk> |
---|---|
date | Sun, 22 Nov 2015 15:23:40 +0000 |
parents | e32fe563e124 |
children |
line wrap: on
line source
/* This code accompanies the textbook: Digital Audio Effects: Theory, Implementation and Application Joshua D. Reiss and Andrew P. McPherson --- Reverb: algorithmic reverb effect based on MVerb See textbook Chapter 11: Reverberation Original code by Martin Eastwood: MVerb (see MVerb.h) Adapted for JUCE by Brecht De Man When using this code (or a modified version thereof) please cite: R. Stables, S. Enderby, B. De Man, G. Fazekas, J. D. Reiss, "SAFE: A System for the Extraction and Retrieval of Semantic Audio Descriptors," 15th International Society for Music Information Retrieval Conference (ISMIR 2014), 2014. --- This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "PluginProcessor.h" #include "PluginEditor.h" #if JUCE_INTEL #define JUCE_SNAP_TO_ZERO(n) if (! (n < -1.0e-8 || n > 1.0e-8)) n = 0; #else #define JUCE_SNAP_TO_ZERO(n) #endif ReverbAudioProcessor::ReverbAudioProcessor() : _numChannels (1) ,_numSamples (1) // dummy - will be set in prepareToPlay ,_sampleRate (1) // dummy - will be set in prepareToPlay ,_density (1.0) ,_decay (1.0) ,_size (1.0) ,_damp (1.0) ,_bandwidth (1.0) ,_predelay (0.0) ,_gain (1.0) ,_mix (0.5) ,_lateEarly (0.5) ,tempInput (1,1)// dummy - will be set in prepareToPlay ,tempOutput (1,1)// dummy - will be set in prepareToPlay ,_lastUIWidth (850) ,_lastUIHeight (650) { // Update all parameters for (int index = 0; index < MVerb<float>::NUM_PARAMS; ++index) { updateParameters(index); } } ReverbAudioProcessor::~ReverbAudioProcessor() { } //----------------------------------------------------------------------------- // P R E P A R E T O P L A Y void ReverbAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) { // If sample rate/block size changes or straight after construction if (_numSamples != samplesPerBlock || _sampleRate != sampleRate) { _sampleRate = sampleRate; _numSamples = samplesPerBlock; _numChannels = getNumInputChannels(); tempInput.setSize (_numChannels,_numSamples); tempOutput.setSize(_numChannels,_numSamples); tempInput.clear(); tempOutput.clear(); _mverb.reset(); _mverb.setSampleRate (_sampleRate); // set reverb sample rate } } //----------------------------------------------------------------------------- // P R O C E S S B L O C K void ReverbAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { int numSamples = buffer.getNumSamples(); int numChannels = buffer.getNumChannels(); for(int channel = 0; channel < numChannels; channel++) { tempInput.copyFrom (channel, 0, buffer, channel, 0, numSamples); } float** input = tempInput.getArrayOfWritePointers(); float** output = tempOutput.getArrayOfWritePointers(); _mverb.process (input, output, numSamples); // processing by MVerb for(int channel = 0; channel < numChannels; channel++) { buffer.copyFrom (channel, 0, output [channel], numSamples); } } //----------------------------------------------------------------------------- // U P D A T E P A R A M E T E R S void ReverbAudioProcessor::updateParameters (int index) { switch(index) { case MVerb<float>::DAMPINGFREQ: _mverb.setParameter (index, _damp); break; case MVerb<float>::DENSITY: _mverb.setParameter (index, _density); break; case MVerb<float>::BANDWIDTHFREQ: _mverb.setParameter (index, _bandwidth); break; case MVerb<float>::PREDELAY: _mverb.setParameter (index, _predelay); break; case MVerb<float>::DECAY: _mverb.setParameter (index, _decay); break; case MVerb<float>::SIZE: _mverb.setParameter (index, _size); break; case MVerb<float>::GAIN: _mverb.setParameter (index, _gain); break; case MVerb<float>::MIX: _mverb.setParameter (index, _mix); break; case MVerb<float>::EARLYMIX: _mverb.setParameter (index, _lateEarly); break; } } //----------------------------------------------------------------------------- // R E S E T void ReverbAudioProcessor::Reset() { _mverb.reset(); // not used } //----------------------------------------------------------------------------- // void ReverbAudioProcessor::releaseResources() { // When playback stops, you can use this to free up any spare memory, etc. } bool ReverbAudioProcessor::hasEditor() const { return true; // (change this to false if you choose to not supply an editor) } AudioProcessorEditor* ReverbAudioProcessor::createEditor() { return new ReverbAudioProcessorEditor (this); } //============================================================================== void ReverbAudioProcessor::getStateInformation (MemoryBlock& destData) { // SAVE STATE INFO XmlElement xml("JRAMReverb_XML"); // Knobs xml.setAttribute("_density" ,_density); xml.setAttribute("_decay" ,_decay); xml.setAttribute("_size" ,_size); xml.setAttribute("_damp" ,_damp); xml.setAttribute("_bandwidth" ,_bandwidth); xml.setAttribute("_predelay" ,_predelay); xml.setAttribute("_gain" ,_gain); xml.setAttribute("_mix" ,_mix); xml.setAttribute("_lateEarly" ,_lateEarly); // then use this helper function to stuff it into the binary blob and return it.. copyXmlToBinary(xml, destData); } void ReverbAudioProcessor::setStateInformation (const void* data, int sizeInBytes) { // LOAD STATE INFO ScopedPointer<XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes)); // make sure that it's actually our type of XML object.. if(xmlState->hasTagName("JRAMReverb_XML")) { // Knobs _density = (float) xmlState->getDoubleAttribute("_density",true); _decay = (float) xmlState->getDoubleAttribute("_decay",true); _size = (float) xmlState->getDoubleAttribute("_size",true); _damp = (float) xmlState->getDoubleAttribute("_damp",true); _bandwidth = (float) xmlState->getDoubleAttribute("_bandwidth",true); _predelay = (float) xmlState->getDoubleAttribute("_predelay",true); _gain = (float) xmlState->getDoubleAttribute("_gain",true); _mix = (float) xmlState->getDoubleAttribute("_mix",true); _lateEarly = (float) xmlState->getDoubleAttribute("_lateEarly",true); } } // This creates new instances of the plugin.. AudioProcessor* JUCE_CALLTYPE createPluginFilter() { return new ReverbAudioProcessor(); } const String ReverbAudioProcessor::getName() const { return JucePlugin_Name; } bool ReverbAudioProcessor::silenceInProducesSilenceOut() const { return true; } int ReverbAudioProcessor::getNumParameters() { return MVerb<float>::NUM_PARAMS; } float ReverbAudioProcessor::getParameter (int index) // externally accessible { switch (index) { case MVerb<float>::DENSITY: return GetDensity(); case MVerb<float>::DECAY: return GetDecay(); case MVerb<float>::SIZE: return GetSize(); case MVerb<float>::DAMPINGFREQ: return GetDamp(); case MVerb<float>::BANDWIDTHFREQ: return GetBandwidth(); case MVerb<float>::PREDELAY: return GetPredelay(); case MVerb<float>::GAIN: return GetGain(); case MVerb<float>::MIX: return GetMix(); case MVerb<float>::EARLYMIX: return GetLateEarly(); default: return 0.0f; } } void ReverbAudioProcessor::setParameter (int index, float newValue) // externally accessible { switch (index) { case MVerb<float>::DENSITY: SetDensity(newValue); break; case MVerb<float>::DECAY: SetDecay(newValue); break; case MVerb<float>::SIZE: SetSize(newValue); break; case MVerb<float>::DAMPINGFREQ: SetDamp(newValue); break; case MVerb<float>::BANDWIDTHFREQ: SetBandwidth(newValue); break; case MVerb<float>::PREDELAY: SetPredelay(newValue); break; case MVerb<float>::GAIN: SetGain(newValue); break; case MVerb<float>::MIX: SetMix(newValue); break; case MVerb<float>::EARLYMIX: SetLateEarly(newValue); break; default: break; } } const String ReverbAudioProcessor::getParameterName (int index) // externally accessible { switch (index) { case MVerb<float>::DENSITY: return "Density"; case MVerb<float>::DECAY: return "Decay"; case MVerb<float>::SIZE: return "Size"; case MVerb<float>::DAMPINGFREQ: return "Damp"; case MVerb<float>::BANDWIDTHFREQ: return "Bandwidth"; case MVerb<float>::PREDELAY: return "Predelay"; case MVerb<float>::GAIN: return "Gain"; case MVerb<float>::MIX: return "Mix"; case MVerb<float>::EARLYMIX: return "Late vs. early reflections"; default: break; } return String::empty; } const String ReverbAudioProcessor::getParameterText (int index) { return String (getParameter (index), 2); } const String ReverbAudioProcessor::getInputChannelName (int channelIndex) const { return String (channelIndex + 1); } const String ReverbAudioProcessor::getOutputChannelName (int channelIndex) const { return String (channelIndex + 1); } bool ReverbAudioProcessor::isInputChannelStereoPair (int index) const { return true; } bool ReverbAudioProcessor::isOutputChannelStereoPair (int index) const { return true; } bool ReverbAudioProcessor::acceptsMidi() const { #if JucePlugin_WantsMidiInput return true; #else return false; #endif } bool ReverbAudioProcessor::producesMidi() const { #if JucePlugin_ProducesMidiOutput return true; #else return false; #endif } int ReverbAudioProcessor::getNumPrograms() { return 0; } int ReverbAudioProcessor::getCurrentProgram() { return 0; } void ReverbAudioProcessor::setCurrentProgram (int index) { } const String ReverbAudioProcessor::getProgramName (int index) { return String::empty; } void ReverbAudioProcessor::changeProgramName (int index, const String& newName) { }