/* ============================================================================== This file was auto-generated! It contains the basic framework code for a JUCE plugin processor. ============================================================================== */ #include "PluginProcessor.h" #include "PluginEditor.h" #include "TemperDsp.hpp" const int kOversampleFactor = 3; //============================================================================== TemperAudioProcessor::TemperAudioProcessor() #ifndef JucePlugin_PreferredChannelConfigurations : AudioProcessor (BusesProperties() #if ! JucePlugin_IsMidiEffect #if ! JucePlugin_IsSynth .withInput ("Input", AudioChannelSet::stereo(), true) #endif .withOutput ("Output", AudioChannelSet::stereo(), true) #endif ), m_params (*this, nullptr) #else : m_params (*this, nullptr) #endif { m_restriction = new RestrictionProcessor(); m_bridge = new FaustUIBridge(m_params); m_lastKnownSampleRate = 0.0; m_currentProgram = -1; // Initialize the dsp units for (int i = 0; i < getTotalNumInputChannels(); ++i) { TemperDsp* dsp = new TemperDsp(); dsp->buildUserInterface(m_bridge); m_dsps.add(dsp); } // Initialize the AudioProcessorValueTreeState root ValueTree root (Identifier("TEMPER")); m_params.state = root; } TemperAudioProcessor::~TemperAudioProcessor() { } //============================================================================== const String TemperAudioProcessor::getName() const { return JucePlugin_Name; } bool TemperAudioProcessor::acceptsMidi() const { #if JucePlugin_WantsMidiInput return true; #else return false; #endif } bool TemperAudioProcessor::producesMidi() const { #if JucePlugin_ProducesMidiOutput return true; #else return false; #endif } double TemperAudioProcessor::getTailLengthSeconds() const { return 0.0; } int TemperAudioProcessor::getNumPrograms() { return 5; // NB: some hosts don't cope very well if you tell them there are 0 programs, // so this should be at least 1, even if you're not really implementing programs. } int TemperAudioProcessor::getCurrentProgram() { return m_currentProgram; } void TemperAudioProcessor::setCurrentProgram (int index) { switch (index) { case 0: setStateInformation(BinaryData::DefaultPreset_xml, BinaryData::DefaultPreset_xmlSize); break; case 1: setStateInformation(BinaryData::StubbedToePreset_xml, BinaryData::StubbedToePreset_xmlSize); break; case 2: setStateInformation(BinaryData::BeeStingPreset_xml, BinaryData::BeeStingPreset_xmlSize); break; case 3: setStateInformation(BinaryData::MorningAtTheDMVPreset_xml, BinaryData::MorningAtTheDMVPreset_xmlSize); break; case 4: setStateInformation(BinaryData::FlyingUnitedPreset_xml, BinaryData::FlyingUnitedPreset_xmlSize); break; default: break; } m_currentProgram = index; } const String TemperAudioProcessor::getProgramName (int index) { switch (index) { case 0: return String("Default"); case 1: return String("Stubbed Toe"); case 2: return String("Bee Sting"); case 3: return String("Morning at the DMV"); case 4: return String("Flying United"); default: return String(); } } void TemperAudioProcessor::changeProgramName (int index, const String& newName) { } //============================================================================== void TemperAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) { auto filterType = juce::dsp::Oversampling::filterHalfBandPolyphaseIIR; m_oversampler = std::unique_ptr>(new juce::dsp::Oversampling(getTotalNumInputChannels(), kOversampleFactor, filterType, false)); // Re-initialize the dsp modules at the upsampled rate. if (m_lastKnownSampleRate == 0.0) for (int i = 0; i < m_dsps.size(); ++i) m_dsps.getUnchecked(i)->init(sampleRate * pow(2, kOversampleFactor)); else for (int i = 0; i < m_dsps.size(); ++i) m_dsps.getUnchecked(i)->instanceConstants(sampleRate * pow(2, kOversampleFactor)); m_oversampler->initProcessing(static_cast (samplesPerBlock)); m_restriction->prepareToPlay(samplesPerBlock, sampleRate); m_lastKnownSampleRate = sampleRate; setLatencySamples(static_cast(m_oversampler->getLatencyInSamples())); } void TemperAudioProcessor::releaseResources() { // When playback stops, you can use this as an opportunity to free up any // spare memory, etc. } #ifndef JucePlugin_PreferredChannelConfigurations bool TemperAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const { #if JucePlugin_IsMidiEffect ignoreUnused (layouts); return true; #else // This is the place where you check if the layout is supported. // In this template code we only support mono or stereo. if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono() && layouts.getMainOutputChannelSet() != AudioChannelSet::stereo()) return false; // This checks if the input layout matches the output layout #if ! JucePlugin_IsSynth if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet()) return false; #endif return true; #endif } #endif void TemperAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { const int totalNumInputChannels = getTotalNumInputChannels(); const int totalNumOutputChannels = getTotalNumOutputChannels(); TemperAudioProcessorEditor* editor = static_cast(getActiveEditor()); // In case we have more outputs than inputs, this code clears any output // channels that didn't contain input data, (because these aren't // guaranteed to be empty - they may contain garbage). // This is here to avoid people getting screaming feedback // when they first compile a plugin, but obviously you don't need to keep // this code if your algorithm always overwrites all the output channels. for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i) buffer.clear (i, 0, buffer.getNumSamples()); // Push input buffer into the Pre spectroscope component. if (editor) editor->m_vizPre->pushBuffer(buffer); // Now the guts of the processing; oversampling and applying the Faust dsp module. const int numInputChannels = buffer.getNumChannels(); const int numInputSamples = buffer.getNumSamples(); juce::dsp::AudioBlock block (buffer.getArrayOfWritePointers(), numInputChannels, numInputSamples); juce::dsp::AudioBlock oversampledBlock = m_oversampler->processSamplesUp(block); // Run the faust processors on each channel of the oversampled block. for (int i = 0; i < numInputChannels; ++i) { auto* processor = m_dsps.getUnchecked(i); auto* data = oversampledBlock.getChannelPointer(i); int len = static_cast(oversampledBlock.getNumSamples()); processor->compute(len, &data, &data); } m_oversampler->processSamplesDown(block); #ifdef TEMPER_DEMO_BUILD // After the Faust processing, add the demo restriction to the output stream m_restriction->processBlock(buffer); #endif // Push resulting buffer into the Post spectroscope component. if (editor) editor->m_vizPost->pushBuffer(buffer); } //============================================================================== bool TemperAudioProcessor::hasEditor() const { return true; // (change this to false if you choose to not supply an editor) } AudioProcessorEditor* TemperAudioProcessor::createEditor() { return new TemperAudioProcessorEditor (*this, m_params); } //============================================================================== void TemperAudioProcessor::getStateInformation (MemoryBlock& destData) { ScopedPointer xml (m_params.state.createXml()); copyXmlToBinary(*xml, destData); } void TemperAudioProcessor::setStateInformation (const void* data, int sizeInBytes) { ScopedPointer xmlState (getXmlFromBinary (data, sizeInBytes)); if (xmlState != nullptr) if (xmlState->hasTagName (m_params.state.getType())) m_params.state = ValueTree::fromXml (*xmlState); } //============================================================================== // This creates new instances of the plugin.. AudioProcessor* JUCE_CALLTYPE createPluginFilter() { return new TemperAudioProcessor(); }