mirror of
https://codeberg.org/armin/mindball.git
synced 2026-09-01 03:40:49 +02:00
init
This commit is contained in:
parent
1b541ba587
commit
78e52e612f
9 changed files with 1553 additions and 0 deletions
196
Source/PluginProcessor.cpp
Normal file
196
Source/PluginProcessor.cpp
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
#include "PluginProcessor.h"
|
||||
#include "PluginEditor.h"
|
||||
|
||||
MindballAudioProcessor::MindballAudioProcessor()
|
||||
: AudioProcessor (BusesProperties()
|
||||
.withInput ("Input", juce::AudioChannelSet::stereo(), true)
|
||||
.withOutput ("Output", juce::AudioChannelSet::stereo(), true)),
|
||||
apvts (*this, nullptr, "Parameters", createParameterLayout())
|
||||
{
|
||||
}
|
||||
|
||||
juce::AudioProcessorValueTreeState::ParameterLayout MindballAudioProcessor::createParameterLayout()
|
||||
{
|
||||
juce::AudioProcessorValueTreeState::ParameterLayout layout;
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (
|
||||
ParameterIDs::feedback, "Feedback",
|
||||
juce::NormalisableRange<float> (0.0f, 1.0f, 0.0001f, 1.0f), 0.35f));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (
|
||||
ParameterIDs::locut, "Lo-Cut",
|
||||
juce::NormalisableRange<float> (20.0f, 4000.0f, 1.0f, 0.3f), 100.0f));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (
|
||||
ParameterIDs::hicut, "Hi-Cut",
|
||||
juce::NormalisableRange<float> (500.0f, 18000.0f, 1.0f, 0.3f), 12000.0f));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (
|
||||
ParameterIDs::time, "Time",
|
||||
juce::NormalisableRange<float> (10.0f, 3000.0f, 1.0f, 0.4f), 300.0f));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterChoice> (
|
||||
ParameterIDs::timeSync, "Time (Sync)",
|
||||
juce::StringArray { "1/16", "1/8", "1/4", "1/3", "1/2", "3/4", "1", "3/2", "2", "3", "4", "8" }, 4));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (
|
||||
ParameterIDs::drywet, "Dry/Wet",
|
||||
juce::NormalisableRange<float> (0.0f, 1.0f, 0.001f, 1.0f), 0.4f));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterBool> (ParameterIDs::sync, "Time Sync", false));
|
||||
layout.add (std::make_unique<juce::AudioParameterChoice> (
|
||||
ParameterIDs::mode, "Mode",
|
||||
juce::StringArray { "Normal", "Invert", "Ping-Pong", "SuperPong" }, 0));
|
||||
layout.add (std::make_unique<juce::AudioParameterBool> (ParameterIDs::doubleTap, "Double", false));
|
||||
layout.add (std::make_unique<juce::AudioParameterBool> (ParameterIDs::center, "Center", false));
|
||||
layout.add (std::make_unique<juce::AudioParameterBool> (ParameterIDs::autopan, "Auto-Pan", false));
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (
|
||||
ParameterIDs::panDepth, "Pan Depth",
|
||||
juce::NormalisableRange<float> (0.0f, 1.0f, 0.001f, 1.0f), 1.0f));
|
||||
layout.add (std::make_unique<juce::AudioParameterBool> (ParameterIDs::bypass, "Bypass", false));
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
const juce::String MindballAudioProcessor::getName() const { return JucePlugin_Name; }
|
||||
|
||||
bool MindballAudioProcessor::acceptsMidi() const { return false; }
|
||||
bool MindballAudioProcessor::producesMidi() const { return false; }
|
||||
double MindballAudioProcessor::getTailLengthSeconds() const { return 10.0; }
|
||||
|
||||
int MindballAudioProcessor::getNumPrograms() { return 1; }
|
||||
int MindballAudioProcessor::getCurrentProgram() { return 0; }
|
||||
void MindballAudioProcessor::setCurrentProgram (int) {}
|
||||
const juce::String MindballAudioProcessor::getProgramName (int) { return {}; }
|
||||
void MindballAudioProcessor::changeProgramName (int, const juce::String&) {}
|
||||
|
||||
void MindballAudioProcessor::prepareToPlay (double sampleRate, int /*samplesPerBlock*/)
|
||||
{
|
||||
engine.prepare (sampleRate, maxDelaySeconds);
|
||||
meterDecay = static_cast<float> (std::exp (-1.0 / (0.4 * sampleRate)));
|
||||
}
|
||||
|
||||
void MindballAudioProcessor::releaseResources()
|
||||
{
|
||||
engine.clear();
|
||||
}
|
||||
|
||||
bool MindballAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
|
||||
{
|
||||
const auto mainIn = layouts.getMainInputChannelSet();
|
||||
const auto mainOut = layouts.getMainOutputChannelSet();
|
||||
|
||||
return mainIn == mainOut
|
||||
&& (mainIn == juce::AudioChannelSet::mono() || mainIn == juce::AudioChannelSet::stereo());
|
||||
}
|
||||
|
||||
void MindballAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer&)
|
||||
{
|
||||
juce::ScopedNoDenormals noDenormals;
|
||||
|
||||
const int numSamples = buffer.getNumSamples();
|
||||
const int numChannels = buffer.getNumChannels();
|
||||
|
||||
if (numSamples == 0 || numChannels == 0)
|
||||
return;
|
||||
|
||||
const bool bypass = *apvts.getRawParameterValue (ParameterIDs::bypass) > 0.5f;
|
||||
if (bypass)
|
||||
{
|
||||
if (!wasBypassed)
|
||||
{
|
||||
engine.clear();
|
||||
wasBypassed = true;
|
||||
}
|
||||
meterDryL = meterDryR = meterWetL = meterWetR = 0.0f;
|
||||
dryMeterL.store (0.0f); dryMeterR.store (0.0f);
|
||||
wetMeterL.store (0.0f); wetMeterR.store (0.0f);
|
||||
return;
|
||||
}
|
||||
wasBypassed = false;
|
||||
|
||||
double bpm = 120.0;
|
||||
if (auto* playHead = getPlayHead())
|
||||
{
|
||||
juce::AudioPlayHead::CurrentPositionInfo pos;
|
||||
if (playHead->getCurrentPosition (pos))
|
||||
bpm = pos.bpm > 0 ? pos.bpm : 120.0;
|
||||
}
|
||||
|
||||
mindball::DelayEngine::Params p;
|
||||
p.feedback = *apvts.getRawParameterValue (ParameterIDs::feedback);
|
||||
p.loCutHz = *apvts.getRawParameterValue (ParameterIDs::locut);
|
||||
p.hiCutHz = *apvts.getRawParameterValue (ParameterIDs::hicut);
|
||||
p.timeMs = *apvts.getRawParameterValue (ParameterIDs::time);
|
||||
p.timeSyncIndex = static_cast<int> (*apvts.getRawParameterValue (ParameterIDs::timeSync));
|
||||
p.dryWet = *apvts.getRawParameterValue (ParameterIDs::drywet);
|
||||
p.mode = static_cast<int> (*apvts.getRawParameterValue (ParameterIDs::mode));
|
||||
p.sync = *apvts.getRawParameterValue (ParameterIDs::sync) > 0.5f;
|
||||
p.doubleTap = *apvts.getRawParameterValue (ParameterIDs::doubleTap) > 0.5f;
|
||||
p.center = *apvts.getRawParameterValue (ParameterIDs::center) > 0.5f;
|
||||
p.autoPan = *apvts.getRawParameterValue (ParameterIDs::autopan) > 0.5f;
|
||||
p.panDepth = *apvts.getRawParameterValue (ParameterIDs::panDepth);
|
||||
p.bpm = bpm;
|
||||
|
||||
wetScratch.setSize (2, numSamples);
|
||||
|
||||
if (numChannels >= 2)
|
||||
{
|
||||
engine.process (buffer.getReadPointer (0), buffer.getReadPointer (1),
|
||||
buffer.getWritePointer (0), buffer.getWritePointer (1),
|
||||
numSamples, p,
|
||||
wetScratch.getWritePointer (0), wetScratch.getWritePointer (1));
|
||||
}
|
||||
else
|
||||
{
|
||||
engine.process (buffer.getReadPointer (0), buffer.getReadPointer (0),
|
||||
buffer.getWritePointer (0), buffer.getWritePointer (0),
|
||||
numSamples, p,
|
||||
wetScratch.getWritePointer (0), wetScratch.getWritePointer (1));
|
||||
}
|
||||
|
||||
const float* outL = buffer.getReadPointer (0);
|
||||
const float* outR = numChannels >= 2 ? buffer.getReadPointer (1) : outL;
|
||||
const float* wetL = wetScratch.getReadPointer (0);
|
||||
const float* wetR = wetScratch.getReadPointer (1);
|
||||
|
||||
for (int i = 0; i < numSamples; ++i)
|
||||
{
|
||||
const float dryL = outL[i] - wetL[i];
|
||||
const float dryR = outR[i] - wetR[i];
|
||||
|
||||
meterDryL = std::max (std::abs (dryL), meterDryL * meterDecay);
|
||||
meterDryR = std::max (std::abs (dryR), meterDryR * meterDecay);
|
||||
meterWetL = std::max (std::abs (wetL[i]), meterWetL * meterDecay);
|
||||
meterWetR = std::max (std::abs (wetR[i]), meterWetR * meterDecay);
|
||||
}
|
||||
|
||||
dryMeterL.store (meterDryL); dryMeterR.store (meterDryR);
|
||||
wetMeterL.store (meterWetL); wetMeterR.store (meterWetR);
|
||||
}
|
||||
|
||||
juce::AudioProcessorEditor* MindballAudioProcessor::createEditor()
|
||||
{
|
||||
return new MindballAudioProcessorEditor (*this);
|
||||
}
|
||||
|
||||
bool MindballAudioProcessor::hasEditor() const { return true; }
|
||||
|
||||
void MindballAudioProcessor::getStateInformation (juce::MemoryBlock& destData)
|
||||
{
|
||||
auto state = apvts.copyState();
|
||||
std::unique_ptr<juce::XmlElement> xml (state.createXml());
|
||||
copyXmlToBinary (*xml, destData);
|
||||
}
|
||||
|
||||
void MindballAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
|
||||
{
|
||||
std::unique_ptr<juce::XmlElement> xml (getXmlFromBinary (data, sizeInBytes));
|
||||
if (xml != nullptr)
|
||||
apvts.replaceState (juce::ValueTree::fromXml (*xml));
|
||||
}
|
||||
|
||||
juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter()
|
||||
{
|
||||
return new MindballAudioProcessor();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue