Skip to content

Instantly share code, notes, and snippets.

@Xenakios
Created April 12, 2018 11:53
Show Gist options
  • Save Xenakios/87d87ba674dbcdfdbd07f50cbfe3d0f2 to your computer and use it in GitHub Desktop.
Save Xenakios/87d87ba674dbcdfdbd07f50cbfe3d0f2 to your computer and use it in GitHub Desktop.
/*******************************************************************************
The block below describes the properties of this PIP. A PIP is a short snippet
of code that can be read by the Projucer and used to generate a JUCE project.
BEGIN_JUCE_PIP_METADATA
name: MultichannelVolume
dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, juce_audio_plugin_client,
juce_audio_processors, juce_audio_utils, juce_core, juce_data_structures, juce_events,
juce_graphics, juce_gui_basics, juce_gui_extra
exporters: xcode_mac
type: AudioProcessor
mainClass: MyPlugin
END_JUCE_PIP_METADATA
*******************************************************************************/
#pragma once
//==============================================================================
class MyPlugin : public AudioProcessor
{
public:
//==============================================================================
MyPlugin()
: AudioProcessor (BusesProperties().withInput ("Input", AudioChannelSet::discreteChannels(64))
.withOutput ("Output", AudioChannelSet::discreteChannels(64)))
{
addParameter(new AudioParameterFloat("mainvolume", "Master volume", -96.0, 12.0, 0.0));
for (int i=0;i<64;++i)
addParameter(new AudioParameterFloat("chanvolume"+String(i), "Channel "+String(i+1)+" volume", -96.0, 12.0, 0.0));
}
~MyPlugin()
{
}
void prepareToPlay (double, int) override {}
void releaseResources() override {}
inline float getFloatParameter(int index)
{
const auto& pars = getParameters();
return *(dynamic_cast<AudioParameterFloat*>(pars[index]));
}
inline void setFloatParameter(int index, float val)
{
const auto& pars = getParameters();
*(dynamic_cast<AudioParameterFloat*>(pars[index])) = val;
}
void processBlock (AudioBuffer<float>& buffer, MidiBuffer&) override
{
ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear (i, 0, buffer.getNumSamples());
float maingain = Decibels::decibelsToGain(getFloatParameter(0));
for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
auto* channelData = buffer.getWritePointer (channel);
float changain = Decibels::decibelsToGain(getFloatParameter(channel + 1));
for (int i = 0; i < buffer.getNumSamples(); ++i)
channelData[i] *= changain*maingain;
}
}
//==============================================================================
AudioProcessorEditor* createEditor() override
{
return new GenericAudioProcessorEditor(this);
}
bool hasEditor() const override
{
return true;
}
//==============================================================================
const String getName() const override { return "MultichannelVolume"; }
bool acceptsMidi() const override { return false; }
bool producesMidi() const override { return false; }
double getTailLengthSeconds() const override { return 0; }
//==============================================================================
int getNumPrograms() override { return 1; }
int getCurrentProgram() override { return 0; }
void setCurrentProgram (int) override {}
const String getProgramName (int) override { return {}; }
void changeProgramName (int, const String&) override {}
//==============================================================================
void getStateInformation (MemoryBlock& destData) override
{
ValueTree state("multichanvolumestate");
auto& pars = getParameters();
for (int i = 0; i < pars.size(); ++i)
state.setProperty("par"+String(i), getFloatParameter(i), nullptr);
MemoryOutputStream stream(destData, true);
state.writeToStream(stream);
}
void setStateInformation (const void* data, int sizeInBytes) override
{
ValueTree state = ValueTree::readFromData(data, sizeInBytes);
if (state.isValid() == true)
{
auto& pars = getParameters();
for (int i = 0; i < pars.size(); ++i)
{
setFloatParameter(i, state.getProperty("par"+String(i), 0.0));
}
}
}
//==============================================================================
bool isBusesLayoutSupported (const BusesLayout& layouts) const override
{
if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono()
&& layouts.getMainOutputChannelSet() != AudioChannelSet::stereo())
return false;
if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
return false;
return true;
}
private:
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyPlugin)
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment